问题描述:

What is the best way to display a view (in my case a login screen) on app resume. From looking around, I've been playing with the applicationDidBecomeActive event in my AppDelegate, but I cannot seem to get my head around how to properly display a view from here.

I've tried to grab the current window by using self.window and/or it's subviews, but from the AppDelegate self.window is nil.

So far this application seems to be wired up correctly, but I am baffled by two things.

A) why is self.window nil from within my AppDelegate's applicationDidBecomeActive event handler.

B) what is the correct/normal way of display a login view (or the like) on application resume.

网友答案:

Implement a custom UIViewController for all of your applications to inherent from. In this view controller implement logic in the viewWillAppear message to determine and show the login screen if necessary.

//CustomViewController.h
@interface CustomViewController : UIViewController
@end

//CustomerViewController.m
@implementation CustomViewController
-(void)viewWillAppear:(BOOL)animated{
    if(login_required){
         LoginViewController *loginView = [[LoginViewController alloc] initWithNibName:@"LoginView" bundle:nil];
         [self presentModalViewController:loginView animated:false];
    }
}
@end

Then, simply, in your login view controller make sure you call:

[self dismissModalViewControllerAnimated:false];

The benefits of this approach are two fold. Firstly, it's a very simple implementation. However, most compellingly, having a base class for an application's view controller presents the opportunity to extract common logic.

网友答案:

Jason,

I have worked on a security tutorial provided by Chris Lowe on raywenderlich.com that was intended to demonstrate how to use basic iOS security to lock the application.

The premise behind this tutorial though was that the application would prompt for login upon first launch and if application was resumed upon unlocking the device through the use of NSNoftificationCenter in viewDidLoad and subscribe the the notifications: deviceWillLock and deviceWillUnlock. All of this assumes the device is set to lock.

Basic iOS Security Tutorial Part 2 - This is the part that has the NSNotification registration.

Basic iOS Security Tutorial Part 1 - This is the first part of the tutorial for clarity.

网友答案:

I also ran into this problem and came across this question whilst researching a solution. I didn't want to create the intermediate super class for my views and I wasn't sure how it would work out with navigation controllers. I have come up with another solution that works well for me - so thought I would share it. It is based around the use of NSNotificationCenter .

In your app delegate create a property to hold a reference to the currently displayed view controller - say currentViewController.

Then in the applicationDidFinishLaunching method, register a block observer to update the currentViewController property like this:

[[NSNotificationCenter defaultCenter] addObserverForName:@"CurrentViewChanged"
                                                  object:nil 
                                                   queue:nil
                                              usingBlock:^(NSNotification *note)
 {self.currentViewController = (UIViewController *)note.object;} ];

In your view controller implementations, update the viewDidAppear methods to notify the observer that a new view controller is being displayed by adding the following line

[[NSNotificationCenter defaultCenter] postNotificationName:@"CurrentViewChanged" object:self];

Finally, include code in the applicationDidBecomeActive method in your app delegate to force the modal display of your login screen.

UIStoryboard *mainStoryBoard = self.window.rootViewController.storyboard;
UnlockViewController *uvc = [mainStoryBoard instantiateViewControllerWithIdentifier:@"modalUnlockView"];
uvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.currentViewController presentViewController:uvc animated:YES completion:NULL];

A couple of additional items to note :-

  1. You can disable the login screen display at anytime by posting a notification where the view controller passed is nil.
  2. You only need to post the notification once for a navigation view controller at the top level. All view controllers in the navigation controller stack will be covered. I haven't checked, but I suspect the same is true for a tab view controller.
  3. If you want to display the login screen the first time you enter the app after startup then include the following line in the applicationDidFinishLaunching method.

    self.currentViewController = self.window.rootViewController;

I hope this is of some use.

Thanks

相关阅读:
Top