Segues and clearing historical ViewControllers from memory

I have an iPad application that has many screens and many segue options. For the moment, I'm just using performSegueWithIdentifier to initiate these segues, and I'm afraid that I'm taking up a lot of memory as the user runs more and more segments. I have seen people recommend using the popToRootViewControllerAnimated: function when using the UINavigationController, but the problem is that I do not use it. How can I stop the spread of VC? As the application works, the user constantly returns to the root VC - effectively the search screen. Therefore, if I could clear the VC stack when such a segue is needed, this will solve my problem, I think, but I have no idea how to do this. Thanks for any suggestions.

+6
source share
4 answers

When you use segues, the flow moves back and forth. When a user moves backward (i.e., presses "backward"), he will not click on the new VC, but he will appear in the VC that already exists. When you exit, the current VC is removed from the stack and memory.

If you have transitions to move backward in the stream, this is wrong. You only need to go forward.

PRELIMINARY PREPARATION FOR SEG

In preparation for segue, you should never create your own view controllers and click on them. The storyboard should do it all for you.

The correct prepareForSegue method should look something like this:

- (void)prepareForSegue:(UIStoryBoardSegue*)segue { if([segue.identifier isEqualToString:"SomeSegue"]) { MyNewViewController *controller = segue.destinationViewController; controller.someProperty = "some value to pass in"; } } 

That is all you need. Please note that you only need this if you intend to pass some information to the new view controller. If you are not transmitting anything, you do not need this method at all.

When the method ends, the new VC will be popped onto the screen by the storyboard file.

UNWIND SEGUES

If you have a random thread (e.g. in your comment), you can use unwind to achieve this.

Your view controller has a function like ...

 - (IBAction)someUnwindAction:(UIStoryboardSegue*)sender { //some action to run when unwinding. } 

He needs to get the UIStoryboardSegue object. If you are configured as an IBAction, you can also access it from Interface Builder.

Now that you want to go A> B> C> B> A, just use the standard push and pop buttons (from the segue and back buttons).

When you want to go A> B> C> A, you can use the unwind segue from controller C.

If you have a cancel button or something in controller C, and this is in the Builder interface, and this should return you to controller A. Then in the Builder interface under controller C you will have a small green square with a door and an arrow pointing to this is. Simply indicate the action of the cancel button on this symbol and select "someUnwindAction". (Note that unwindAction is in A, the button is in C.) Then Xcode uses this so that you go back to A all the time and delete any memory and everything. If you want, you can send additional information back to A.

If you want to access this reversal session from C programmatically, you can run ...

 [self performSegueWithIdentifier:"someUnwindAction" sender:nil]; 

This will also return to A.

+10
source

imho I do not see problems using segues, it is much simpler than anything else. If you are worried about memory consumption, just open your application and see how much it eats and how often your "memory pressure handler" is called.

+1
source

ok I think I understood this. It seems to work.

As I keep returning to the general VC, I put the code in the places where I want to go to this "root" VC in order to clear the VC stack.

I am still executing the actual segue in my regular code

 [self performSegueWithIdentifier:@"editBackToSearch" sender:self]; 

However, in the "prepareForSegue:" method, I no longer create a new VC object, instead, do any work that is outstanding for me (I save my data), and then clear the VC stack with the following code.

 UIViewController *vc = self; while ([vc presentingViewController] != NULL) { vc = [vc presentingViewController]; } [vc dismissViewControllerAnimated:NO completion:nil]; 

It seems to work smoothly and has the desired effect (confirmed through the profiler) on the release of memory that these VC sucks.

One last comment - for some reason I couldn’t animate the firing command, this seemed to cause an endless loop and lead to EXC_BAD_ACCESS. If the animation is set to NO, it works great.

Thank you for your help.

0
source

Swift 3 : this prevents memory leaks in Swift 3 and 4

 @IBAction func entryViewSelected(_ sender: UIButton) { self.dismiss(animated: true, completion: nil) } 
0
source

All Articles