有一次登录iPhone的正确方法?

时间:2013-05-24 16:12:57

标签: iphone objective-c

我正在尝试创建一个首次加载时需要登录的应用。用户成功登录后,凭据将存储在钥匙串中,因此用户无需继续登录。

这是我编写的以下代码的快速模型;使用AppDelegate正确的方法来处理哪个View首先显示?

AppDelegate.h

#import <UIKit/UIKit.h>
#import "KeychainItemWrapper.h"
#import "ViewController.h"
#import "TestBViewController.h"
#import "User.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) TestBViewController *mainVC;  //  User see's after loggin in
@property (strong, nonatomic) User *user;
@property (strong, nonatomic) KeychainItemWrapper *keychainItem;

- (void)saveKeychainUsername:(NSString *)username andPassword:(NSString *)password;
- (void)loadLoggedInViewControllers;

@end

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"AppUniqueID" accessGroup:nil];

//    [self.keychainItem resetKeychainItem];

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

// Override point for customization after application launch.

NSString *password = [self.keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *username = [self.keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];

NSLog(@"username: %@, password: %@", username, password);

if ([username length] <= 0 || [password length] <= 0) {
    // Login VC
    ViewController *loginVC = (ViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:@"Login"];
    self.window.rootViewController = loginVC;
} else {
    [self loadLoggedInViewControllers];
}

return YES;
}

- (void)loadLoggedInViewControllers {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

//  Attempt to login user
self.user = [[User alloc] init];

self.user.name = @"Bob";
self.user.hasAccess = YES;
//  If user is no longer valid (for whatever reason) remove his keychain information so we can save the new ones.

//  Valid user! Skip Login VC
self.mainVC = (TestBViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:@"Main"];
self.mainVC.user = self.user;

self.window.rootViewController = self.mainVC;
}

ViewController.m - 将此视为我的LoginViewController

- (IBAction)storePassButtonTap:(id)sender {

if ([[username text] length] > 0 && [[password text] length] > 0) {
     AppDelegate *shareDelegate = [[UIApplication sharedApplication] delegate];

    [shareDelegate saveKeychainUsername:[username text] andPassword:[password text]];

    [shareDelegate loadLoggedInViewControllers];
} else {
    if ([[username text] length] <= 0) {
        //  Error message
    }

    if ([[password text] length] <= 0) {
        //  Error message
    }
}
}

2 个答案:

答案 0 :(得分:2)

我不推荐这样做。我过去已经这样做了,并且我遇到了一些问题,例如,一旦我像这样更改了appdelegate的rootviewcontroller属性,代理就没有工作。看起来它已在iOS 6中修复,但我的理解是这是不寻常的,不应该这样做。

而是将一个虚拟视图控制器作为rootviewcontroller,并添加其他视图控制器作为其childViewController。您可以通过这种方式删除和添加任何视图控制器。

答案 1 :(得分:1)

我个人不会。我使用故事板并将视图控制器设置为根。如果我需要这样做,我会将视图控制器留空(如果需要一分钟登录,可能有一个活动指示器),在这里运行登录代码,然后移动到登录segue或主应用程序segue。

确保下一个屏幕都隐藏了后退按钮,因此用户无法返回此屏幕。

我喜欢将appDeleage留给重新建立tcp连接并在输入背景时关闭它们。