How to access previous view controller from a dismiss command - ios

Throughout my app I use a navigation controller to push and pop my view controllers. When I pop from one ViewController, I check to see if I can reload the data in the previous one with this:
_ = self.navigationController?.popViewController(animated: true)
if let previousViewController = self.navigationController?.viewControllers.last as? AnimalsVC {
previousViewController.tableView.reloadData()
}
This works every time, but now I need to do the same with another view, but it's not apart of the navigation controller because I modally present (instead of pushing it to the navigation controller). Now there's no way I can access the previous ViewController like before and I can not figure out how to access the previous ViewController.
How can I access the previous ViewController to reload the tableview like the example code without accessing the navigation controller?
I know this is possible with notifications, but I prefer not to use that method if possible!

First of all, It's not necessary to access the previous ViewController to reload tableview(or any other func)
I recommend you to use Delegate to achieve the same feature.
Holding a reference to the previous viewController in the way you mentioned will make your app very hard to maintain when your app gets more complicated.

You can call tableview.reloadData() in viewWillAppear method in the controller that you present modally

Related

how can I second time show my view controller without calling viewdidload?

here is my scenario case.
Initially for going to this VC without loading is hidden.when I click to first view controllers button it goes to second view controller.When I click button from secondVC it come back to first one and for going to this VC without loading button is now visible.Now when I click for going to this VC without loading I want to show my second view controller without reload because my previous loaded data for second view controller is needed.So how can I do that?
the actual scenario of my app look like this.My first VC
and the second one.
It's a picture of sound cloud but the case is same.
First possible solution,
Add SecondViewController as child view controller of FirstViewController using container view in Storyboard.
Every time you want to remove SecondViewController just hide/remove it with custom animation block.
Keep the reference of SecondViewController in FirstViewController
Second possible solution,
Create shared data object.
Then you can use that shared data object in any view controller, regardless of saving the state of any view controller.
I would create an object where i put the data und pass this from ViewController to ViewController by properties. Maybe this is to simple but it should work.

viewDidLoad vs ViewWillAppear in IOS

Please help me with this. I have created a simple project with two views as shown. I have attached the images for my storyboard and swift files. So, I read that viewdidload will be executed only once while loading the view into the memory. But, when I make a transition from secondview to the firstview the viewdidload is executing again and so is the print statement in the viewdidload method.
Someone please explain me this.
viewDidLoad is not called once for the Application. It is get called once for that viewController when the view holds memory and loaded.
So as many number of of time you push to the viewController, that many times it will call the viewDidLoad
viewDidLoad() — Called when the view controller’s content view (the top
of its view hierarchy) is created and loaded
viewWillAppear() — Intended for any operations that you want always to
occur before the view becomes visible.
For more info about this look at the link : https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson4.html
So if the view is already in memory (Like your case), then no need to push again, only need to pop back by this code
self.navigationController?.popViewControllerAnimated(true)
You should not make transition from secondViewController to firstViewController for back. Pop the second view controller by this code to back:
self.navigationController?.popViewControllerAnimated(true)
When you make a transition it makes a new instance from your firstViewController but when you pop the second view controller it dismiss your secondViewController and shows your last viewed viewController again.
Or
in the case that you are not using navigationController you should use below code to dismiss your secondViewController
self.dismissViewControllerAnimated(true, completion: {});
The main point is that you should not use new transition for back.
The simplest way:
1.First embed your ViewController in NavigationController
2.Call to this (instead of create segue for backing)
navigationController?.popToRootViewController(animated: true)
viewDidLoad will be called only once

UIViewController getting deallocated after dismissing a previously presented modal viewController

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?

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

Why is my ViewController being removed from NavigationController.ViewControllers collection

I am navigating between screens in my iOS application.
BaseView.NavigationController.ViewControllers
As I switch screens, I keep a reference to the previous screen in a static variable.
At some point, one of my items gets removed from BaseView.NavigationController.ViewControllers even though it's still a valid viewcontroller and IsLoaded is still set to True/YES.
When I use (pardon my C#/MonoTouch)
BaseView.NavigationController.PopToViewController(CurrentViewController,false);
to show it again, I get NSInternalInconsistencyException Reason: Tried to pop to a view controller that doesn't exist. This is understandable because it's no longer in the ViewController collection.
The way I am switching screens is I am keeping a reference to he various screens and calling a common method to show the screen. In that method I use this logic to determine if I should push or pop.
if (CurrentViewController.IsViewLoaded)
{
BaseView.NavigationController.PopToViewController(CurrentViewController,false);
}
else
{
BaseView.NavigationController.PushViewController(CurrentViewController,true);
}
My question is where did it go and why would it have been removed from ViewControllers collection and when it's StillLoaded=true/YES?
If I understand correctly, you're using NavigationController.PopToViewController(controller); to navigate back to a certain view controller but keep a reference of the View Controllers that are popped from the navigation stack.
What I think is happening is because you're keeping a reference to these View Controllers, they're still in memory and thus the IsViewLoaded property is still true despite the View Controller not actually existing on the navigation stack.
Rather than using the IsViewLoaded property, you should check whether the View Controller exists in the NavigationController.ViewControllers array, if it does then Pop to it, if it doesn't then push it.
E.g.
if (BaseView.NavigationController.ViewControllers.Contains(CurrentViewController))
{
BaseView.NavigationController.PopToViewController(CurrentViewController,false);
}
else
{
BaseView.NavigationController.PushViewController(CurrentViewController,true);
}
Edit
So you mention you'd like a view to persist on the navigation stack. Well, using PopToViewController will remove ALL View Controllers between the TopViewController and the specified Controller.
In order to achieve what you're wanting, you could directly manipulate the NavigationControllers.ViewControllers array. Only problem with this is you'll lose the nice animations that the Push/Pop methods provide.
// Changes order of View Controllers currently in the stack. You can also add/remove
// controllers using this method.
NavigationController.ViewControllers = new UIViewController[]{
NavigationController.ViewControllers[1],
NavigationController.ViewControllers[0],
NavigationController.ViewControllers[3],
NavigationController.ViewControllers[2]};

Resources