I have set up a very simple project with no storyboard, one window and one UINavigationController containing a plain old UIViewController as rootViewController. In the AppDelegate I've set the UINavigationController's delegate to self and implemented
navigationController:didShowViewController:animated which contains 1 line:
NSLog("didShow viewController")
When I launch my app the UINavigationControllerDelegate method navigationController:didShowViewController:animated gets called twice.
AppDelegate:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDelegate {
var window: UIWindow?
var vc1: FirstViewController?
var nav1: UINavigationController?
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
NSLog("didShow viewController")
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
vc1 = FirstViewController()
nav1 = UINavigationController(rootViewController: vc1!)
nav1?.delegate = self
window = UIWindow(frame: UIScreen.main.bounds)
if let window = window {
window.backgroundColor = UIColor.white
window.rootViewController = nav1
window.makeKeyAndVisible()
}
return true
}
}
FirstViewController:
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have tried this in more complicated environments - An app with a UITabBarController and 2 UINavigationControllers as the viewControllers for the UITabBarController. Oddly the UINavigationControllerDelegate methods fire twice the first time a UINavigationController is shown, but will only fire once after that.
Anyone have any insight as to how to correct this? What I believe to be correct behavior based on the documentation is that navigationController:didShowViewController:animated should be only called once in this sample app. I have also checke dot make sure the navigationController and viewController params in the delegate method are the same object.
Thanks in advance!
EDIT: Here's the callstack from each call. All in UIKit code, not mine!
1st call:
29 elements - 0 : "0 ??? 0x0000000115145377 0x0 + 4648620919" - 1 : "1 ??? 0x0000000115145462 0x0 + 4648621154" - 2 : "2 Test 0x0000000105f22d00 main + 0" - 3 : "3 Test 0x0000000105f21e11 _TToFC4Test11AppDelegate20navigationControllerfTCSo22UINavigationController7didShowCSo16UIViewController8animatedSb_T_ + 97" - 4 : "4 UIKit 0x0000000106bab7a8 -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] + 1660" - 5 : "5 UIKit 0x0000000106e8839e -[UINavigationTransitionView _notifyDelegateTransitionDidStopWithContext:] + 421" - 6 : "6 UIKit 0x0000000106e88677 -[UINavigationTransitionView _cleanupTransition] + 629" - 7 : "7 UIKit 0x0000000106a58f07 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 222" - 8 : "8 UIKit 0x0000000106a54bcb +[UIViewAnimationState popAnimationState] + 305" - 9 : "9 UIKit 0x0000000106e8810b -[UINavigationTransitionView transition:fromView:toView:] + 2582" - 10 : "10 UIKit 0x0000000106bb01d1 -[UINavigationController _startTransition:fromViewController:toViewController:] + 3301" - 11 : "11 UIKit 0x0000000106bb06b3 -[UINavigationController _startDeferredTransitionIfNeeded:] + 843" - 12 : "12 UIKit 0x0000000106bb17f1 -[UINavigationController __viewWillLayoutSubviews] + 58" - 13 : "13 UIKit 0x0000000106da32bc -[UILayoutContainerView layoutSubviews] + 231" - 14 : "14 UIKit 0x0000000106a9020b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268" - 15 : "15 QuartzCore 0x000000010bfbf904 -[CALayer layoutSublayers] + 146" - 16 : "16 QuartzCore 0x000000010bfb3526 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 370" - 17 : "17 QuartzCore 0x000000010bfb33a0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24" - 18 : "18 QuartzCore 0x000000010bf42e92 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294" - 19 : "19 QuartzCore 0x000000010bf6f130 _ZN2CA11Transaction6commitEv + 468" - 20 : "20 QuartzCore 0x000000010bf6fb37 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 115" - 21 : "21 CoreFoundation 0x000000010910f717 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23" - 22 : "22 CoreFoundation 0x000000010910f687 __CFRunLoopDoObservers + 391" - 23 : "23 CoreFoundation 0x00000001090f4038 CFRunLoopRunSpecific + 440" - 24 : "24 UIKit 0x00000001069c702f -[UIApplication _run] + 468" - 25 : "25 UIKit 0x00000001069cd0d4 UIApplicationMain + 159" - 26 : "26 Test 0x0000000105f22d37 main + 55" - 27 : "27 libdyld.dylib 0x000000010a19a65d start + 1" - 28 : "28 ??? 0x0000000000000001 0x0 + 1"
2nd call:
20 elements - 0 : "0 ??? 0x00000001151456e7 0x0 + 4648621799" - 1 : "1 ??? 0x00000001151457d2 0x0 + 4648622034" - 2 : "2 Test 0x0000000105f22d00 main + 0" - 3 : "3 Test 0x0000000105f21e11 _TToFC4Test11AppDelegate20navigationControllerfTCSo22UINavigationController7didShowCSo16UIViewController8animatedSb_T_ + 97" - 4 : "4 UIKit 0x0000000106ba949b -[UINavigationController viewDidAppear:] + 421" - 5 : "5 UIKit 0x0000000106b7595e -[UIViewController _setViewAppearState:isAnimating:] + 704" - 6 : "6 UIKit 0x0000000106b7863b __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke + 42" - 7 : "7 UIKit 0x0000000106b76a7b -[UIViewController _executeAfterAppearanceBlock] + 86" - 8 : "8 UIKit 0x00000001069d992f _runAfterCACommitDeferredBlocks + 634" - 9 : "9 UIKit 0x00000001069c67bc _cleanUpAfterCAFlushAndRunDeferredBlocks + 532" - 10 : "10 UIKit 0x00000001069e957d __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke_2 + 155" - 11 : "11 CoreFoundation 0x000000010910fb5c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12" - 12 : "12 CoreFoundation 0x00000001090f4e54 __CFRunLoopDoBlocks + 356" - 13 : "13 CoreFoundation 0x00000001090f45ee __CFRunLoopRun + 894" - 14 : "14 CoreFoundation 0x00000001090f4016 CFRunLoopRunSpecific + 406" - 15 : "15 GraphicsServices 0x000000010b100a24 GSEventRunModal + 62" - 16 : "16 UIKit 0x00000001069cd0d4 UIApplicationMain + 159" - 17 : "17 Test 0x0000000105f22d37 main + 55" - 18 : "18 libdyld.dylib 0x000000010a19a65d start + 1" - 19 : "19 ??? 0x0000000000000001 0x0 + 1"