Detect Child UIViewController being popped - ios

I'm sure this will be a simple answer, maybe a method I'm missing to implement. Here goes:
In my Controller1 I use a pushViewController to push a new view Controller2 onto my view stack. I'm getting a back button.
Now, when Back button is pressed in my Controller1 I want to be able to detect that Controller2 is being popped and we're back in Controller1. Makes sense?
I was trying to do that with ViewDidAppear, but I'm not sure how to detect a popped controller. There are other answers here but they all show examples in Controller2 on viewWillDisappear
How would I do that in Swift?

Without knowing more you should pass a reference of the first controller to the second controller so that the second controller can tell the first when it is done (this is a simple delegate relationship, it could also be implemented using a block / closure).
Ideally the first controller should be responsible for dismissing the second controller, either when it gets this callback or, more appropriately, directly when the 'dismiss' button is tapped.

Related

Call function in ViewController after RelationshipSegue

I am having a multiple UIViewController embedded in a UITabbarController.
These are connected by Relationship Segues.
The starting point, VC1 initially loads data and is then processed to a "detail" view.
Whenever I change tabs and go back to VC1, the application gets stuck, as viewDidLoad is not called.
Is there a way to trigger a function each time VC1 is segued to?
the application gets stuck, as viewDidLoad is not called
The application is not stuck. It is working perfectly. viewDidLoad is called when a view controller is created and loads its view. That only happens once in the life of the view controller. When you leave a view controller and come back to it, it is still there (i.e. it is not being created from scratch), so naturally viewDidLoad is not called.
If your goal is to hear about the fact that the tab bar controller is switching to VC1, give the tab bar controller a delegate and implement tabBarController(_:didSelect:) or similar.
Even better, configure things so that there is no need to do this. If there is common data that is accessed by both view controllers, architect things so that a view controller sends new data up to a data controller and the data controller broadcasts news of the change down to all view controllers that need to know this.

iOS Swift Push Segue Catch Trigger Back Button Function

What function gets triggered when a user hits the back button on a push page? I need to set some properties before going back to the previous page. ViewWillDisapper is not what I'm looking for
You will want to use either viewWillDisappear or viewDidDisappear to monitor a user going back on a pushed page (assuming you mean this is inside a navigation controller).
Just like when you call your instance method of UINavigationController to "pushViewController:(BOOL)animated:" guess what method is called to POP a view controller? try something like
[self.navigationBar.backButton //Not sure if this is what its called addTarget:self selector:#selector(popViewController)]
and fill in the rest of the method with UIEventTouchUpInside so when the user presses the back button on navigation bar it will jump into you're overrided function.
Make your View inherit UINavigationController protocols and then overide popViewController method.
I suggest looking at UINavigationController class reference if that didn't answer your question.

Sending data between ViewControllers without segues

Is there a way to send data between ViewControllers without using segues?
Specifically I have two ViewControllers embedded in a TabBarViewController. One is called PlayingCardViewController and the other is called HighScoreViewController. I want to pass a class HighScore from PlayingCardViewController to HighScoreViewController. I want to transfer the data from PlayingCardViewController as soon as I press the redeal button in PlayingCardViewController but I don't want to transition to the HighScoreViewController as that would be jarring for the player.
I thought about using segues and holding the HighScores in an array and passing that to all the VC's that PlayingCardViewController is connected to but I realized that that seems overly complicated and there must be a simpler way to pass the data upon hitting the redeal button.
Some relevant links
Passing Data between View Controllers
I'm just going to do this with bullet points:
You could implement a custom tab bar controller (your own UITabBarController subclass), and use this instead of a basic UITabBarController.
Your PlayingCardViewController could have its own delegate protocol/property.
The delegate protocol could define a method like playingCardVC:didSetHighScore:.
Your tab bar controller would be the PlayingCardViewController's delegate.
The tab bar controller could keep a reference to the HighScoreViewController.
When your tab bar controller gets the playingCardVC:didSetHighScore:, it could pass whatever you want to your HighScoreViewController.

Segue to home view

I am trying to segue back to a home screen and pop everything from the stack (of views?)
I am using UINavigationController:
[self.navigationController popToRootViewControllerAnimated:YES];
Where shall I call this method? I have tried in -(void) prepareForSegue which does not work.
Basically I want to make sure when I go back to home screen there is no back button on the left of the title.
Home screen here refers to the welcome screen of my App.
I am not sure which part of my code shall be posted. Please comment if you need to see my code.
Thank you in advance.
Assuming you're using a Storyboard, and a UIButton declared over there is the one that triggers that action you wanna perform, you should declare an IBAction: -(IBAction)buttonPressed:(id)sender; in the .h and implement it in the .m. Inside that method should appear that [self.navigationController popToRootViewControllerAnimated:YES]; code. Also remember to attach that action to that UIButton when touch up inside in the storyboard.
Hope it helped!
I think your confusion is around the concepts of what a segue is and how it relates to the navigation controller stack. The stack is exactly the same as the basic data structure stack (http://en.m.wikipedia.org/wiki/Stack_(abstract_data_type)) in that it's a last-in-first-out store. When you segue, you're normally adding to that stack, e.g. Pushing a new VC onto the stack. A back button in most cases would not be doing that. It would be popping, or removing from the stack. Which is why you probably wouldn't call pop methods from the prepareForSegue method. Instead try calling it at some other point, like when they tap the back button, or after some action has taken place.

About passing data between view controllers with delegate

FIRST SCENARIO:
I have two view controllers
VC1 has a button, and a label
VC2 has a button, and a text field
theres a modal segue between VC1 -> VC2
when I run this segue, we set VC1, as the delegate for VC2.
We go to VC2, fill out the text field, hit the button, and VC2 is dismissed.
some delegated method is run on VC1, and VC1.label is filled in.
question: is there any way to do this without dismissing VC2.. for example, if VC2.button just modal segues us back, or slides us back to VC1 im assuming it re initializes the viewcontroller and the label wont be changed. do you always have to dismiss the view controller
SCENARIO 2:
again, two view controllers.
this time its reversed.. so i have
VC1 with a textfield and a button
VC2 with a label and a button
soo now we fill out VC1, and we expect it to show up on VC2. But without a segue, they have no relationship. is there any way to pass data between VCs using delegation without one initial segue? Is this segue requirement to use delegation something specific to view controllers? Im assuming it is because in other cases we just instantiate objects, and use their delegate methods. but with view controllers we want to reference one that is already created, and not instantiate a second one.
note: im using story boards
1) You could do it without dismissing VC2, but it's not a good idea. You don't want to segue "back" to one, because, as you surmised, you're actually creating a new instance of VC1, and then if you segue again to VC2, you're creating a new instance of that too. You will keep piling up more and more instance of the two controllers and none will ever be deallocated.
2) Again, your instincts are correct -- you need to somehow get a reference to the instance of VC2 that your putting on screen in order to set yourself as delegate. You don't have to have a segue to do that, you could create the second controller in code and do a manual push or presentViewController, but that's functionally, the same as doing a segue.
Sorry, dont fully understand what you want .. but here is my take.
FIRST SCENARIO:
Why would you need to update the view that isnt on screen ?
Just update in viewWillAppear.
Otherwise you can have the delegate update it when you finish editing that textfield.
SCENARIO 2:
You need a link between the view controllers, use segues makes easy, set as delegate and pass along the info. Why make it harder than it needs to be
Many things have delegates, textfields etc, you are just saying this class / obj will do something for something else.
There are many youTubes about delegates, ie
http://www.youtube.com/watch?v=eNmZEXNQheE
For more info see this stack post - it covers everything you need to know
Passing Data between View Controllers

Resources