i have a label with a TapGesture in a table view cell that should dismiss the view controller, which is embedded in a Navigation controller, if its pressed.
Normally I would do it like that:
_ = navigationController?.popViewController(animated: true)
OR
self.dismiss(animated: true)
But this is not working inside the table view cell class.
Would be great if someone could help me!
For it to work you should pass that obligation to the viewController which is managing your tableView. So above your tableViewCell class declare a protocol with a function which the delegate (In this case the ViewController which is holding your tableView) should implement when called. So when a delegate gets called inside a ViewController dismiss the ViewController if it was modally presented and pop it if it was pushed, so one of the methods you mentioned above should work. If you Don't know how custom protocols work, try reading this article https://medium.com/#aapierce0/swift-using-protocols-to-add-custom-behavior-to-a-uitableviewcell-2c1f09610aa1
Related
Is there any way to make sure resetScene() gets called only after the view controller vc has been dismissed? Any help would be appreciated.
vc.present(activityVC, animated:true, completion: nil)
self.resetScene()
to make sure resetScene() gets called only after the view controller vc has been dismissed
Put the call to resetScene() inside the view controller vc's viewDidDisappear.
Or put it inside self's viewDidAppear and check first to make sure that the reason why we are reappearing is that vc was dismissed.
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.
I have a viewController containing a UITableViewController. This UITableViewController is populated by an array. When User presses populated cells they segue with a segue set to 'Manuel Segue : Show' this creates a back button UINavigation bar item. Inside this viewController the user is able to add Items to the array populating the parent UITableViewController. The problem is that when i segue back using the UINavigationbarItem it does not call viewDidload on the UITableViewController, there by not updating the UIViewTableCells. I have to close application to make it call viewDidload... How do i make it call ViewDidload when returning from the Manuel segue show? All help appreciated.
The pushing view controller is not unloaded when another view controller is shown above. As viewDidLoad: is only called once in the view lifecycle, this would then not be called when the segue is unwound.
Updating your tableview in viewWillAppear: or viewDidAppear: would cause this to be called whenever this view is displayed.
viewWillAppear would perhaps be better if you don't want to show the user the table reloading when not needing to asynchronously load data.
Read more on iOS view controller lifecycle here:
https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson4.html#//apple_ref/doc/uid/TP40015214-CH6-SW3
I've created a UIViewController, and insert a container view in it, which embed a UITableViewController. As the image described above.
When user click the Table View Cell, I'd like to add a UIBarButton on the Navigation bar.
But, how can I manage this? I can rise the DatePicker when click on Table View Cell, but when I call self.presentingViewController in table view controller implementation file, it returns (null), same as when I call self.parentViewController
You're probably trying to access the parent controller too early. If you log self.parentViewController in viewDidLoad, it will return null, but it should return the correct controller from viewDidAppear, and certainly from the didSelectRowAtIndexPath method. Using parentViewController in this context is correct, not presentingViewController.
I'd suggest to implement the UITableViewController Delegates and Datasource Methods in the ViewController itself.
That way you don't have to worry about accessing the ViewController containing the UITableView.
I have a Navigation Controller with a View Controller displaying a button. The button is linked to another View Controller using a push segue which automatically adds a top navigation bar with a back button. This all works fine. Pressing the back button slides off the 2nd view and returns to the 1st.
I have a button on the 2nd View Controller, that when pressed runs some code and a delegate call back to the 1st View Controller. Again this works fine.
Now I just need to dismiss the 2nd pushed View from code as if the back button was pressed.
I have tried using dismissModalViewCcontrollerAnimated and dismissViewControllerAnimated, however they both dismiss the whole Navigation Controller which removes view 2 and 1 (returning bak to my main menu).
Whats the correct way to slide off the view.
Obtain a reference to your UINavigationController and call
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
on it.
In Swift it would be calling the method
navigationController?.popViewController(animated: true)
If we use push segue, then use popViewController
#IBAction func backButtonClicked(_ sender: Any) {
self.navigationController?.popViewController(animated: false)
}
In swift you can also call:
self.navigationController?.popToRootViewControllerAnimated(true)
On Objective-C is
[self.navigationController popViewControllerAnimated:YES];
for a jump to the first root controller
[self.navigationController popToRootViewControllerAnimated:YES];
or is a possible move to the specific controller
[self.navigationController popToViewController:(nonnull UIViewController *) animated:(BOOL)];
animation specific animation process of move the controller. If the animation is false the controller will appear without animations.
The UIViewController must be from one which is on the stack.
If NavViewController is used with UIModalPresentationFullScreen then the below line will work
self.navigationController?.dismiss(animated: true, completion: nil)