How to call viewWillDisappear method in Tabbar Application having navigations also - iphone

I have created 5 Tabs in my application. In Tab1 i have UITableView. On didSelectRowAtIndexPath i am navigating to another UIView in which I am showing my all 5 Tabs. And I also play song in that navigated view.
Now when I click Back button in navigation and i again go to my original view, i am able to call viewWillDisappear (as expected and normal situation).
But when I click directly another tab then viewWillDisappear is not called in the navigated View. Why this Happens??
I have just thought in a way that when I directly clicks the another Tab then the view in Tab1 will call viewWillDisappear. But the navigated view will not call that method.
So what could be possible solutions?? kindly give some hints...

I got the viewWillDisappear to work by calling
self.definesPresentationContext = true
in viewDidLoad()
Otherwise, viewWillDisappear wasn't getting called. And this is what I have in it:
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.searchController.active = false
tableView.reloadData()
}
Hope this helps.

I think that you need to catch the event when you switch between tabs. When you switch from Tab1 to Tab2, as you expect, viewWillDisappear of Tab1 will not be called. Instead, the viewWillAppear of Tab2 will be called.
Else if you want to catch the event when you switch tabs, check this link.

That is because the you have created tabBarController and you are pushing it as a viewController from the mainView.
So whole TabBarController is treated as one viewController.
Hope this helps you.

if you want to call this method create the nsnotification center object viewWillDisappear
and when you want to call this method post this notification.

That's how I got it to work.
// UITabBarControllerDelegate
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
print("Selected view controller")
// do stuff...
self.navigationController?.setNavigationBarHidden(false, animated: false)
return true
}

Related

swift xcode iOS: can I re-use a loaded modal fullscreen view controller?

I have a storyboard with two view controllers. First one, VC_1, has one button that opens 2nd one - VC_2.
VC_2 also has a button that opens VC_1.
Both controllers have almost identical code:
class VC_1: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
print(“VC_1 loaded")
}
override func viewDidAppear(_ animated: Bool){ print(“VC_1 appeared") }
override func viewDidDisappear(_ animated: Bool){ print(“VC_1 disappeared") }
#IBAction func btnShowVC_2(_ sender: UIButton)
{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
secondVC = storyboard.instantiateViewController(identifier: “VC_2”)
secondVC.modalPresentationStyle = .fullScreen
show(secondVC, sender: self)
}
}
The difference is only in "VC_2" instead of "VC_1" in the 2nd controller code.
I have seen this View Controller creation code in Apple documentation and many other examples around the Internet.
When I press the button on the VC_1, I see in the debug window, that VC_2 is loaded and appeared, and VC_1 is disappeared. And same, of course, happens when I press the button on VC_2 - it disappears, and VC_1 is loaded again.
My questions are:
what happens with View Controller object after "viewDidDisappear" has been called? Does it really disappear from memory, or "disappear" only means "you cannot see it on the screen?". I do not see "viewDidUnload" in the documentation...
I suppose that "viewDidLoad" means that new View Controller object was created in memory. Is there any way to load the View Controller object only once, and then hide and show it without causing "viewDidLoad" to be called? I tried to do it with global variable "secondVC" but got "Application tried to present modally an active controller" error.
viewDidDisappear: called after the view is removed from the windows’
view hierarchy. No, View controller object just left the view property. By the way the amount of memory used by view controllers is negligible. So dont think about too much. If you want to catch when Your View controller object release from the memory put
deinit { print("vc deallocated") }
viewDidUnload, it has been deprecated since the iOS
6, which used to do some final cleaning.
Partly true. Keep in mind ViewDidload called one time for the life cycle of view controller. There is a method called before viewdidload but this is not related with your question.
In addition to "There is a method before viewdidload" -> loadView( ) is a method managed by the viewController. The viewController calls it when its current view is nil. loadView( ) basically takes a view (that you create) and sets it to the viewController’s view (superview).

Is there a way to call a function once a View Controller leaves the view stack?

ViewDidDisapear and ViewWillDisappear are still called if another View Controller is above the (say, for example, you push a view controller on top of it). Is there a function that is only called once the view controller is removed from the navigation stack? Adding a function to the back button works, but what if the user decides to to the edge pan gesture to dismiss the view? Is there an action that accounts for both events?
Yes, I can think of few ways to do this off the top of my head
One option would be to add some code to a dealloc method of the UIViewController.
If you don't expect the view controller controller to get deallocated when it leaves the stack you can also set a UINavigationControllerDelegate for the UINavigationController and define
func navigationController(_ navigationController: UINavigationController,
didShow viewController: UIViewController,
animated: Bool) {
guard let poppedViewController =
navigationController.transitionCoordinator?.viewController(forKey: .from)
<Do something with the popped VC>

How can I debug a Swift's function call stack?

I have a problem that a screen gets pushed twice. The problem is I don't know which pushViewController that is doing that, and I have so many of them. So I want to add a breakpoint to navigationController.pushViewController() function so I can see what is the previous call stack that call that function. I don't need to see the inside of pushViewController. I just need that the breakpoint stop whenever the function pushViewController at navigationController gets called. But I can't put breakpoint on the open func pushViewController() at navigationController code. How can I do that?
You can extend UINavigationController and override pushViewController function.
class MyNavigationViewController : UINavigationController {
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
super.pushViewController(viewController, animated: animated)
}
}
And then you if you are using storyboard, change the class of your navigation controller to MyNavigationViewController and also in the code if you creating navigation controller from code.

Swift dismissViewController from Segue - macOS

I have a secondary ViewController that appears programmatically via a Storyboard segue:
func actioncall ()
{
performSegue(withIdentifier: "showIgnoreVC", sender: self)
}
)
This function is part of the main ViewController, and is called via an NSNotification from the AppDelegate, which in turn is triggered by a Menu Item click.
However, even though the segue is connected to the main ViewController, the following code does not dismiss the secondary view:
#IBAction func dismiss(_ sender: Any)
{
print("Hello? Gonna close?")
self.presenting?.dismissViewController(self)
}
There are no errors, the function is called upon the correct Dismiss button click, but the secondary view does not dismiss. I have tried every variation of dismissViewController to no avail.
When I use a button on the Main view to activate the same segue, everything works as it is supposed to. I simply do not wish to clutter up the main View with a bunch of buttons.
Any ideas are appreciated, thank you very much.
dismissViewController works only for view controllers, that were presented modally (using Present Modally Segue)
As said in the answer to this SO question, you should dismiss view controllers, presented by Show Segue, like this:
navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

How to detect view controller dismissed or not

In iOS app, there may be several view controllers. They may perform segues from one to another. the question is how to detect each view controller about whether it is dismissed or not when implementing segue. Thanks.
You have access to:
override func viewWillDisappear(animated: Bool) {
}
override func viewDidDisappear(animated: Bool) {
}
// Called when the view controller will be removed from memory.
deinit {
}
Which can help you managed things based on that state of a view controller.
I'm not sure if you can detect whether or not it was dismissed, but you can set a variable "viewControllerDismissed = true" in performSegueWithIdentifier that will be detected in the VC behind the one being dismissed.