Is there a View Will Appear, from specific View Controller method? - ios

I have a home-screen, which has a push segue to various other view controllers. However, when I return from one (and only one) of these view controllers back to the home screen, I want the home-screen to reload one of its functions. The viewWillAppear method is useful (if I implement it on the home screen) because it is called when I return to the home screen, but is there something I can add, that will essentially check "was I sent back to the home-screen from -this specific- view Controller"? Not very eloquently worded I apologise.
The way I am doing this at the moment is to define a universal boolean variable, which becomes true when I am on the special view controller, then in the viewWillAppear method, if the boolean == true I reload the function. I don't like using these universal variables though, it feels error prone.
n.b. When I say universal variable, I mean one that is defined above the class, this may not be the proper term

When you are sent from another view controller back to the home screen, are you using an unwind segue? If so, the home view controller should have a method of this form:
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue{
}
Inside this method, you can check if the sourceViewController is of a certain class:
if([unwindSegue.sourceViewController isKindOfClass:[otherTypeOfviewController class]]){
//perform the tasks you need carried out
}

Related

Order of viewWillAppear calls

If I have multiple view controllers being presented and dismissed in any order, can I be sure that iOS calls viewWillAppear methods in the right order (i.e. order of appearance)?
I cannot find any specific information about this in the documentation.
I think this is all you need to know about viewWillAppear from the docs:
This method is called before the view controller's view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call super at some point in your implementation.
Only thing that comes to mind that might not be absolutely clear is that this callback is called on the presenting view controller when presented view controller is going to be dismissed (so presenting view controller is going to appear again).
Therefore if A is a root, A.viewWillAppear will be called before it will appear on the screen. Then, if A presents B, just before B becomes visible, B.viewWillAppear will be called. And when B is being dismissed, A.viewWillAppear will get called again, since its view will appear again.
viewWillAppear() is called the first time the view is displayed and it is also called when the view is displayed again, so it can be called multiple times during the life of the view controller object.
It’s called when the view is about to appear as a result of the user tapping the back button, closing dialog, or when the view controller’s tab is selected in a tab bar controller, or a variety of other reasons. Make sure to call super.viewWillAppear() at some point in the implementation

Determine when leaving a view controller that it's not a segue

I'm trying to save some data upon user leaving this specific view controller (either by hitting nav back button or different tab bar button or exiting the app). However, there is one segue going forward, in this case I don't want to save the data yet, it will get saved on the next view controller with additional data.
How can I determine in viewWillDisappear: (or anywhere else) that user is leaving the view controller, but differentiate that it is not through the segue? I've looked at self.isBeingDismissed() and self.isMovingFromParentViewController() and I can't seem figure out a good solution. Any insight is greatly appreciated, thanks!
You might want to try this method instead of viewWillDisappear-
fun willMoveToParentViewController(parent : UIViewController?)
{
super.willMoveToParentViewController(parent);
if parent == nil {
//This means the current controller is getting popped out of the nav stack
}
}
Documentation:
Called just before the view controller is added or removed from a
container view controller.
Since navigation controller is a container controller, when it removes the top most controller, it should call this method with parent value as nil.
HTH

Distinguishing the user action causing a view controller to be pushed

I'm subclassing UINavigationController and want to in order to add the ability to add previously popped view controllers back onto the stack, akin to a forward button in a web browser.
When the user presses a button, I want to add the most recently popped off view controller back onto the stack. I do this by getting the view controller at the top of my custom stack, and calling pushViewController:animated: with it.
In the case where taps on a table view cell or something to go forward a new way into the view hierarchy, I want to clear my "popped view controllers" stack. Similar to how if the user clicks on a new link in a web browser the "forward" history is cleared.
This is where my issue lies. I don't know how to differentiate between when I call pushViewController:animated: in order to restore a view controller, and when the user taps a cell to push one. In the latter case, I want to clear my stack, but in the former I don't want to.
I can't figure out what to do here. In a perfect world pushViewController:animated: would have userOptions: parameter or something on it that would allow me to distinguish between how it's being used, but unfortunately that parameter doesn't exist.
Such an issue must come up rather frequently. How would I deal with it in this case? How would I differentiate between the circumstances in which the method is being called?
If I follow you correctly one common approach to doing this is:
Your "goForward" method should call your superclass' pushViewController:animated:
Override pushViewController:animated: to call both your superclass' pushViewController:animated: and your "clearStack" method.
It seems to me that you need two different methods in your subclass. One for the case where you want to restore a view controller, and one where you want to clear the stack. Both will perform some custom logic and call pushViewController:animated: on super.

Showing master view on some pages and preventing the user from hiding it

I have an iPad app with a UISplitviewController set as the root view controller of UIWindow. The master view controller (i.e. the view controller of the left view) is the UISplitViewController's delegate with the delegate method shouldHideViewController returns YES, this means when the app first launches the left view will be hidden and can be shown (and hidden) by the user gesture, i want to show the master view when i navigate to detail pages and prevent the user from hiding it using the gesture, i've tried to call shouldHideViewController method on the delegate to let it returns NO the second time it got called but this time it has no effect, the master view keeps hidden in detail pages and can be shown with the user gesture.
any ideas to achieve showing of the master view with this scenario would be highly appreciated.
This may only be a partial answer because I'm not sure what you mean that you call shouldHideViewController method on the delegate. My understanding is that only the UISplitView should call this method. If you call it, then it will not effect the UISplitView, because it wasn't what made the call. In other words, the delegate method is used by UISplitView to get some information (and allow you a place to do additional things to other stuff) but it is not used as a way to tell the UISplitView what to perform.
Having said that, at least for the gesture activation/deactivation, I would think that in splitViewController:shouldHideViewController:inOrientation: you could do something like
[svc setPresentsWithGesture:NO];
I don't see any way to programmatically tell the UISplitViewController to display or hide the master view controller because the delegate only tells it if it should proceed in presenting or hiding the master when it is going to try and do that. It does seem like there should be a way to do this though.

Conditional segue based on current view controller

All,
I'm trying to perform segues based on the identity of the currently displayed view controller. Essentially, I've given my VC's storyboard ID's and now want to access these in code. So, essentially I want some logic whereby if existing view controller is first, I want to perform firstSegue and if it's second, I want to perform secondSegue and so on. Also, my VC's are part of a navigation controller and I know that the navigation controller has a property where i can view the present view controller or something like that. But I wasnt sure what it was. Can somebody help me out? Again, I foresee my code being something like:
(IBAction)firstButtonPressed:(id)sender
{ if (presentviewcontroller ==a) // If the current view controller Is A
{
[self performSegueWithIdentifier:#"segueA" sender:self];}
if(storyboard.viewcontroller==b)//If the current view controller is B
{
[self.performSegueWithIdentifier:#"segueB" sender:self];}
}
Can someone help me out with some code?
I'm not sure I understand your setup, but if it's what I think it is, then you don't need to know from which controller the button was pressed. Even though the 2 controllers inherit from a common ancestor, they are still separate instances, and only the segue that is connected to that instance will be called. So, each of your controllers could have a segue with the same identifier, lets say button1Segue. Then the code in AncestorController could just be:
-(IBAction)firstButtonPressed:(UIButton *)sender{
[self performSegueWithIdentifier:#"button1Segue" sender:self];
}
The correct segue will be performed because whichever instance's button was pressed, only that instance's segue will go.
If you were to set different tags for each view in interface builder, you could use the following
if (self.view.tag == 1) {
NSLog(#"something");
}
I successfully use this method in my app for different views, and it works well.

Resources