Janum Trivedi Janum Trivedi - 1 month ago 18
iOS Question

Presenting a specific view controller from AppDelegate

I am trying to present a view controller (a passcode request type view) every time my app becomes active. Once the correct passcode is entered, it should pop off the stack. The passcode view I'm trying to push isn't the initial view controller, so I'm having trouble accessing it from the AppDelegate's applicationDidBecomeActive.

I also tried pushing the passcode view from my MainViewController's ViewWillAppear, but it doesn't get called when the app becomes active; only when the screen is refreshed.

I've been researching similar problems across SO the past couple days, but I'm still not understanding the proper method. I've heard that I might not be able to push the view this way because the applicationDidBecomeActive may be called before the Storyboard or NavigationController is connected/initialized/etc.

If anyone could provide me with the correct way to push/present the view, or if there's somewhere else that'd be better to do this type of thing, I'd appreciate it.

Solved: I just deleted the view from storyboard and used a nib instead. I used:

PasscodeUnlockVC *passcodeUnlock = [[PasscodeUnlockVC alloc] initWithNibName:@"PasscodeUnlockVC" bundle:[NSBundle mainBundle]];
[(UINavigationController *)self.window.rootViewController pushViewController:passcodeUnlock animated:NO];


View hierarchy data:

(gdb) po [[(id)UIApp keyWindow] recursiveDescription]
<UIWindow: 0x736a4b0; frame = (0 0; 320 480); layer = <UIWindowLayer: 0x7367b40>>
| <UILayoutContainerView: 0x76977a0; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x769de60>>
| | <UINavigationTransitionView: 0x7692110; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x769a8c0>>
| | | <UIViewControllerWrapperView: 0x73868d0; frame = (0 64; 320 416); autoresize = W+H; layer = <CALayer: 0x75510e0>>
| | | | <UIView: 0x76b93e0; frame = (0 0; 320 416); autoresize = W+H; layer = <CALayer: 0x7386850>>
| | <UINavigationBar: 0x73664b0; frame = (0 20; 320 44); clipsToBounds = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x7366550>>
| | | <UINavigationBarBackground: 0x7360ea0; frame = (0 0; 320 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7366520>> - (null)
| | | <UINavigationItemView: 0x76b95e0; frame = (160 21; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x76aa8e0>>
| | | <UINavigationItemButtonView: 0x7550650; frame = (5 7; 73 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7368b40>>
Current language: auto; currently objective-c
(gdb)

Answer

I suggest you use applicationWillEnterForeground:, not applicationDidBecomeActive:, because it works better with multitasking gestures. For example, you don't want to put up the lock screen if the user double-clicks the home button to display the task bar, and then dismisses the task bar without changing apps.

Presumably your AppDelegate has a window property, and you know that your window's root view controller is a UINavigationController.

- (void)applicationWillEnterForeground:(UIApplication *)application {
    PasscodeViewController *pvc = [[PasscodeViewController alloc] init];
    [(UINavigationController *)self.window.rootViewController pushViewController:pvc animated:NO];
    // [pvc release]; if not using ARC
}