Now I have 3 Viewcontrollers like this:
HomeViewcontroller = VC1.
Viewcontroller2 = VC2 --> has a table view with cells on it.
Viewcontroller3 = VC3 --> allows me to edit each cell in VC2 or delete.
I am using NavigationController between Viewcontrollers, to get the nice "back" button :)
Lets say I am in VC1, I press a button and I go to VC2.
Now let's say I have 4 cells.
I press cell number 2 and I go to VC3, where I can edit what I have in the cell or even delete it.
This is all working OK (tested it).
Let's say I want to delete that cell. I have a button on VC3 and I use it and I delete the cell (this is tested and also working OK).
Now when I do this I push into VC2 again like this:
let viewController = storyboard?.instantiateViewController(withIdentifier: "VC2") as! VC2!
self.navigationController?.pushViewController(viewController!, animated: true)
The problem is that when I do this I go to VC2 but I doesn't reload my tableView has it should (the erased cell it's still there).
To fix this I tried adding some code in VC2, in the viewDidLoad:
self.tableView.reloadData()
Now I managed to do it work. I mean when I delete a cell from VC3 I am pushed to VC2 and the cell it's not there. However If I press the back button it takes me to the previous cell that I have deleted,,, If the cell doesn't exist anymore I don''t want it to take me there. I want it to take me to the VC1 (home).
How can I make this work?
Perhaps I should do this in another way and not pushing like that?
Practically you are doing wrong, when delete / edit operation done on VC3 and you want to come back on VC2, why you are doing pushViewController , you have to apply popViewController.
You have to apply self.navigationController?.popViewController(animated: true) coming back to VC2 from VC3.
Remove
let viewController = storyboard?.instantiateViewController(withIdentifier: "VC2") as! VC2!
self.navigationController?.pushViewController(viewController!, animated: true)
Add
self.navigationController?.popViewController(animated: true)
Also
Put reloadData() method for table view in viewWillAppear. like below code.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
}
Some reference material to read about UINavigationController.
https://developer.apple.com/reference/uikit/uinavigationcontroller
Put your self.tableView.reloadData() in an override of viewWillAppear. viewDidLoad is only called once after the viewController is created, but viewWillAppear is called every time it is about to appear on screen.
Also, don't use a push to return to VC2 from VC3. You should pop the current viewController.
self.navigationController?.popViewController(animated: true)
Instead of pushing ViewController2 again from ViewController3 you need to create one delegate and implement that delegate within your ViewController2 now create the instance of that delegate in viewController3 and set that delegate when you are moving from ViewController2 to ViewController3. Now when you update or delete data of ViewController2's simply use that delegate to call method from ViewController2 and inside that method update your DataSource and reload the tableView.
N.,
Normally when different view controllers are embedded in a navigation controller, you push up the stack and going back you pop from the stack. As I understand your story it seems you are only pushing new view controllers on the stack.
Your first view controller is VC1. You press a button and you push the new view controller on the stack, VC2. The navigation controller now has 2 view controllers on the stack VC1 and VC2. Then you select a cell in the table view of VC2 and it takes you to VC3.
The navigation controller now holds 3 view controllers on the stack VC1, VC2 and VC3. Now you delete a cell and you push a NEW view controller on the stack, which is again a VC2, but a new one. The navigation controller now has four view controllers on the stack VC1, VC2, VC3 and another instance of VC2.
I would assume you have a model object containing the data in the table views of VC2 and VC3. When you delete the cell you should delete the cell in your model object and not push a new VC2 on the stack, but dismiss the VC3. You can do this with an #IBAction in VC2 to which your delete button is connected. It then pops the VC3 from the stack and you land back in VC2 in the IBAction method to which you have linked the delete button. The navigation controller then only has 2 view controllers on the stack again, VC1 and VC2.
In that IBAction method you can reload the table view and the table view will call the datasource method
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
This method will look at your model object and not find the deleted data and your cell is gone.
When you then push the back button, the navigation controller pushes the VC2 from the stack and is left with only one view controller VC1. You will land back on your page.
Hope this helps.
Related
I have a View Controller (1) that lists some entities in a table. If the user wants to add a new entity they click and "add" button where they segue to VC2 (a view containing a form to fill in the necessary fields to add a new entity). After they add an entity at VC2 I want them to be automatically forwarded to the details screen VC3 related to the entity that they just added. Normally this detail screen VC3 is a segue from VC1 when they click on an existing entity from the table.
currently in VC2 I have
//go back to VC1
navigationController?.popViewController(animated: true)
//Segue to VC3
VC1?.performSegue(withIdentifier: "goToDetail", sender: self)
The problem with this is the user sees the view change back to VC1 then changes to VC3 due to the "pop" and then segue.
If I omit the navigationController?.popViewController(animated: true) and go directly to VC3 it works as expected except when the user uses the back button from VC3 where it returns them to VC2 which is the form they filled out but I really want them to skip VC2 and go back to VC1.
Well you have two obvious choices, both very easy.
Either go ahead and push from VC2 to VC3 and then remove VC2 from the stack, by calling setViewControllers(_:animated:) with [VC1,VC3], or else...
Change what happens when the user pops from VC3 so that we pop all the way down to VC1, by calling popToRootViewController(animated:).
I have a CoreData project where:
-VC1 has a table of items. Clicking a cell invokes didSelectRowAtIndexPath func which leads to VC2 with presentViewController method.
-VC2 shows detail of the selected item. There is a button Edit which leads to VC3 where I can edit the details of the item and save, or another button to go back to VC1.
-From VC3 to VC2: When I edit the detail and save in VC3, VC3 will be dismissed, VC2 will reappear and the updated information is shown. No problem.
-From VC2 to VC1: When I press back button in VC2, VC2 will be dismissed, and VC1 is shown but the table Data are original ones and the updated detail/item is not shown. It will be shown only if I quit the app and rerun it.
I tested with print() to see if VC1's viewDidAppear(where I have the standard fetchAndResults and tableView.reloadData()) will kick in when returning back from VC2, and I noticed it doesn't print.
Does it mean VC1 is not disappeared when VC2 is presented with didSelectRowAtIndexPath func?
If so, how do I make VC1 to rerun its viewdidappear?
I tried to reload VC1's tableview from VC2 just before dismiss, but it gives me unexpected nil error.
Help me! Thanks.
i'm turning around for days.
I've got a hierarchy of 3 ViewControllers.
Start in VC1, from there you can load VC2. In VC2 you can load VC3.
My navigation works fine VC1->VC2->VC3 and the same backwards.
VC3 allows the user to go back to VC1.
I wonder if it's possible to tell VC3 that VC1 is now it's delegate.
It would work fine with VC2 but I'd like to use the datas saved in VC3 in VC1.
Create a delegate to pass value from one class to another.
Then set delegate in both VC1 and VC2 where VC1 recieves from VC2 and VC2 recieves from VC3
Then call for delegate from VC3 and pass value to VC2 .In VC2 the called method implement the invocation of its delegate to VC1 and the value is there in vc1
VC3-->del-->VC2-->del->VC1
If VC1 is the delegate of VC2, you could just assign VC2's delegate property to the delegate property of VC3
In your VC2 #implementation before VC3 is pushed onto the navigation stack:
vc3Instance.delegate = self.delegate
I suggest adding a weak property called 'master' for example in each view controller and make it point to the view controller that presented it. Once you do that, you can then reach VC1 (and all it's data) from VC3 in the following way:
VC1ViewController *vc1 = self.master.master;
I have the base ViewController which i my main menu(VC1).
From there I navigate to another VC which displays a UITable(VC2). From here i can call
[self.parentViewController dismissModalViewControllerAnimated:YES];
To move back to the main menu. That works fine.
If i load another VC(V3) with displays a UIWebView from VC2 and want to jump back to the main menu(VC1), how can this be done in the best way?
So I navigate VC1->VC2->VC3 and then want to jump VC3->VC1.
My app doesn't have a UINavigationViewController or anything like that.
Many Thanks,
-Code
You could try creating a method in the parent vc (vc2) that you call from vc3 that does the following:
-(void)dismissTwo
{
[self dismissModalViewControllerAnimated:NO];
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
That's untested, but give it a shot.
Its tricky if you used navigation controller you could have popped to root view controller using poptorootviewcontroller.
However in your case if you can implement a delegates for VC2 and VC3. In the delegate for VC3 in VC2 dismiss VC3 and call delegate of VC2 which is implemented in VC1.
So basically the flow is as follows
Create VC1
When you create VC2 from VC1 assign delegate to VC1
When you create VC3 from VC2 assign delegate to VC2
From this point on you can pass messages in a cleaner way between the view controllers.
I have a navigationController and 3 View controllers. VC1 pushes VC2 and VC2 uses PresentModalViewController to display the 3rd VC
When VC2 uses presentModalViewController to show VC3, is the VC3 actually pushed on the navigationcontroller stack?
viewdidload of VC3 is called only 1st time. My goal is to show VC3 with a new imageView everytime. Where do I add the code to do that? viewdidappear and viewwillappear of VC3 is not fired either
It is my understanding that VC3 will be in the view hierarchy of VC2 and not the navigationController. In order to be added to the view hierarchy of the navigationController you would have to push VC3 onto it.
viewDidLoad should only be called once, unless the nib file itself was unloaded from memory, due to low memory. The documentation states that viewWillAppear and viewDidAppear should be called on VC3, so I don't know why they are not.
Update
I just tested and VC3 does have -(void)viewDidAppear:(BOOL)animated called. Make sure that the signature on the selector is correct