我正在尝试创建一个首次加载时需要登录的应用。用户成功登录后,凭据将存储在钥匙串中,因此用户无需继续登录。
这是我编写的以下代码的快速模型;使用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
}
}
}
答案 0 :(得分:2)
我不推荐这样做。我过去已经这样做了,并且我遇到了一些问题,例如,一旦我像这样更改了appdelegate的rootviewcontroller属性,代理就没有工作。看起来它已在iOS 6中修复,但我的理解是这是不寻常的,不应该这样做。
而是将一个虚拟视图控制器作为rootviewcontroller,并添加其他视图控制器作为其childViewController。您可以通过这种方式删除和添加任何视图控制器。
答案 1 :(得分:1)
我个人不会。我使用故事板并将视图控制器设置为根。如果我需要这样做,我会将视图控制器留空(如果需要一分钟登录,可能有一个活动指示器),在这里运行登录代码,然后移动到登录segue或主应用程序segue。
确保下一个屏幕都隐藏了后退按钮,因此用户无法返回此屏幕。
我喜欢将appDeleage留给重新建立tcp连接并在输入背景时关闭它们。