I have an app that uses a storyboard. I am going from the "main view controller" to the others using standard segues, and I am dismissing the other viewControllers with dismissViewController. (note, they are mostly being displayed in form sheet).
Thing is, when it returns to the main view controller, I need to do some cleanup (clear out arrays, reload a tableview and so on). How would I go about doing this, since i cannot use viewDidLoad or viewDidAppear?
I think the best solution it is add block (for example closeActionBlock) for your presented controller and call this block when you hide controller. (How it is implement you can see in Objective-C Block Property with Xcode code completion)
Related
I have a view controller. It has some data and values in it. Then it presents modally to another view and moves around and some stuff happens. Then at some point, you self.dismissViewController(). Once back at the original view, can I count on the original data being there? Any help is greatly appreciated. Thanks in advance!
They will not be affected unless you specifically write code to do that for you.
For example, if you call a network request in the viewDidLoad() and add the data to some views, labels, etc. Then you leave that ViewController and come back, nothing will change, i.e., the network request will not be called again.
If you do want to change values in the ViewController every time it appears, use the viewDidAppear() delegate method.
for reloading view on dismiss you must use viewWillAppear() because this working every time before rendering view
calling dismissViewController will remove the viewController. If you do not have a strong reference to the view controller stored elsewhere, dismissing it releases the memory associated with it.
If the presented view controller must return data to the presenting view controller, use the delegation design pattern to facilitate the transfer.
So if the data was not modified in the presented controller then it will be the same then you can depend on it
reference: Apple docs
From an initial ViewController I've modally presented a second ViewController using a ShowDetail segue in the storyboard and a performSegueWithIdentifier: method call. The problem is when I dismiss this modal ViewController with the method dismissViewControllerAnimated: the initial ViewController is reinstantiated calling the viewDidLoad again.
I've tried using a Push segue instead of the Show Detail and the initial ViewController keeps allocated in the background as it should.
What might be going on? The initial ViewController never even calls the memory warning method.
Have you tried unwindSegues?
***** Long explanation ahead, skip to solution if you want the quick way *****
First of all, if it is a ShowDetail, it is not a modal view. Do try to see which is your case.
Modal segues can carry information backwards, but are a bit more complicated than push ones.
If you are modally presenting it, you should use Present Modally instead of a ShowDetail.
A modal presentation will always take the top view position in the stack, and Show Detail does as well, depending in how your views are set. For instance, if you have a detail view in stack, IT will be replaced rather than the stack top view.
Try choosing up to a specific segue, I particularly recommend modal assuming you need more than simple pushes (Or the Show would have closed the problem, being the equivalent to the previous deprecated push. If you only need something simple, Show is the way)
Now we've cleared this, what probably is happening is that the view is being removes since Show Detail replaces views instead of pushing them, and it has to perform init again.
***** Solution: *****
The solution then should be not to lose the view when replacing, and reinitializing it, what dismissViewControllerAnimated: does. If you use unwind segues, though, the view should be replaced BUT retained by ARC.
The following link has the best explanation all over the net about how to use it:
What are Unwind segues for and how do you use them?
I'm new to iOS dev and am not entirely sure on Storyboards/Segues/Pushing and Popping.
So in my app I have a navigation controller with 5 view controllers leading from one to another.
When it reaches the last view controller i have a segue to the first and I have a few tasks listed in the prepareForSegue method.
Out of curiosity I decided to check what happens to the [self.navigationController.viewControllers count]. I found that it keeps growing and growing which doesn't 'feel' correct.
Am i handling going back to the first screen correctly? The prepareForSegue method is useful as it allows me to send some data back to the first segue. Is it possible to maybe say when you go back clear all views on that navigation controller?
Thanks
You can use an unwind segue. Here's a good tutorial:
pragmaticstudio.com/blog/2013/2/5/unwind-segues
Make sure to create the unwind action method before you wire it up in the storyboard otherwise it won't show up when you drag to 'Exit'. That was the most confusing part for me when I first set one up. The tutorial does it in the correct order so if you follow it you should be fine.
Also, here's a sample I put together showing how to transfer data back in an unwind segue. It uses a modally presented view controller but the technique is the same:
github.com/soleares/AddToTableView
No, you should never go backwards with a segue (other than an unwind). Segues ALWAYS instantiate new controllers, so you're not actually going back to the first controller, you're just creating a new instance, which gets added to the stack. So either go back with an unwind segue or use popToViewController:animated:. Using an unwind segue will allow you to use prepareForSegue, and it does cause all the controllers in between to be deallocated (if you have no other strong pointers to them).
What is the difference between viewDidLoad and viewDidAppear? What kind of initialization or custom code goes into those functions?
e.g. presentModalViewController works only when present in viewDidAppear and not on viewDidLoad.
viewDidLoad is called exactly once, when the view controller is first loaded into memory. This is where you want to instantiate any instance variables and build any views that live for the entire lifecycle of this view controller. However, the view is usually not yet visible at this point.
viewDidAppear is called when the view is actually visible, and can be called multiple times during the lifecycle of a View Controller (for instance, when a Modal View Controller is dismissed and the view becomes visible again). This is where you want to perform any layout actions or do any drawing in the UI - for example, presenting a modal view controller. However, anything you do here should be repeatable. It's best not to retain things here, or else you'll get memory leaks if you don't release them when the view disappears.
See: https://developer.apple.com/documentation/uikit/uiviewcontroller
Simply put, you would want to create any controls or arrays in viewDidLoad, where as in viewDidAppear is where you would want to refresh those controls or arrays.
viewDidLoad is called once when the controller is created and viewDidAppear is called each time the view, well, DID appear. So say you have a modal view that you present, when that view is dismissed, viewDidAppear will be called, and viewDidLoad will not be called.
I've seen this question a couple of times but never really answered. I'm wondering if there is an acceptable/clean way to dismiss all launched view controllers and return to the initial view controller when using storyboards (say from an action within a spawned view controller).
I know how to use delegates, but, I'd prefer to not have my initial view controller implement delegates for every possible spawned view controller. Instead, I'd just like a home button that cleans everything up and returns to the initial view controller from anywhere in the app.
Thoughts?
EDIT: Just for clarity, assume I am NOT using UINavigation Controllers.
EDIT2: Is it possible to just access the methods of the "initial view controller" from anywhere in the app like you might do with the appDelegate?
This should do it at any point. Just stick it in an IBAction and hook it up to a button :)
[self.navigationController popToRootViewController];
I ended up using a singleton. Seems to work quite well.
On the initial load of the initial view controller, I set the view controller as the singleton's property. I can then execute the following code in any action method on any view controller in the app to dismiss all view controllers and return to the initial view controller.
initialViewControllerManager *ivcManager = [initialViewControllerManager sharedInstance];
LPViewController *ivc = ivcManager.initalViewController;
[ivc dismissModalViewControllerAnimated:YES];
May not be the "right" answer, but, seems to work. And, given the complexity of my scenes, relying exclusively on UINavigationControllers would be very complicated.