寫在前面
僅以此文記錄APP登錄砸狞、退出登錄比較簡單核心的流程。
流程梳理
登錄流程有兩種情況镀梭,1刀森、未登錄時,打開APP先進入登錄頁面报账,點擊登錄后進入首頁研底。2埠偿、已登錄時,打開APP直接進入首頁榜晦。
這里我們已最精簡的流程圖表示這兩種登錄情況冠蒋。
1:未登錄情況
2:已登錄情況
代碼編程
我項目是用的RAC+MVVM
開發(fā)的,可能有些地方架構(gòu)不同乾胶,但是道理都是相通的抖剿。
一、LoginService
首先繼承NSObject
創(chuàng)建LoginService
用來做“登錄”功能的數(shù)據(jù)處理识窿。還有在登錄成功后需要存儲用戶的一些信息斩郎,這些信息往往我們將其以model的形式存儲。
在LoginService.h中最主要的兩個方法喻频。
@property (nonatomic, strong) UserInfoModel *signUser;
+ (instancetype)shareInstance;
- (RACSignal *)loginWithLoginName:(NSString *)loginName
loginPwd:(NSString *)loginPwd;
- (void)logOut;
在.m中:
1缩宜、先說- (RACSignal *)loginWithLoginName:(NSString *)loginNameloginPwd:(NSString *)loginPwd
方法。請求服務(wù)器登錄成功后接受返回的參數(shù)甥温,返回的用戶信息我們用signUser
接收锻煌。
if ([responseObject isKindOfClass:[NSString class]]) {
//
return @(NO);
} else {
NSDictionary *resultDic = responseObject[@"result"];
UserInfoModel *userInfo = [UserInfoModel yy_modelWithDictionary:resultDic];
self.signUser = userInfo;
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:loginName forKey:USERNAME];
[userDefault setObject:[CryptoHelper Encrypt:loginPwd] forKey:PASSWORD];
[userDefault setObject:@"ISLOGIN" forKey:ISLOGIN];
NSData *signUserData = [NSKeyedArchiver archivedDataWithRootObject:userInfo];
[userDefault setObject:signUserData forKey:SIGNUSERINFO];
[userDefault synchronize];
self.isLogin = YES;
return @(YES);
}
在這個方法中,使用NSUserDefaults
將用戶名
和密碼
進行本地化存儲窿侈,(注意:密碼不要以明文方式存儲,需要加密)秋茫。另:將登錄狀態(tài)也存儲在NSUserDefaults
本地中史简,以便在AppDelegate
中使用。
這里有一個點肛著,我們都知道
NSUserDefaults
是不可以直接存儲對象的圆兵。但是我們又想存signUser
這個UserInfoModel。這里需要對UserInfoModel
進行處理枢贿。UserInfoModel
繼承自NSObjec殉农,并遵循NSCoding
協(xié)議。并實現(xiàn)兩個NSCoding
代理方法:
//1:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.adminID = [aDecoder decodeObjectForKey:@"adminID"];
self.adminName = [aDecoder decodeObjectForKey:@"adminName"];
}
return self;
}
//2:
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.adminID forKey:@"adminID"];
[aCoder encodeObject:self.adminName forKey:@"adminName"];
}
這樣我們在存儲model對象的時候局荚,先將model轉(zhuǎn)成NSData類型超凳,然后將data存儲即可。
NSData *signUserData = [NSKeyedArchiver archivedDataWithRootObject:userInfo]; [userDefault setObject:signUserData forKey:SIGNUSERINFO];
2耀态、實現(xiàn)logOut
方法
在注銷登錄的方法中轮傍,將本地存儲的密碼、登錄狀態(tài)標(biāo)識首装、用戶信息清除创夜,這里我們保留了“賬號”,后面將會提到這個用處仙逻。
- (void)logOut {
self.isLogin = NO;
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
// [userDefault removeObjectForKey:USERNAME];
[userDefault removeObjectForKey:PASSWORD];
[userDefault removeObjectForKey:ISLOGIN];
[userDefault removeObjectForKey:SIGNUSERINFO];
[userDefault synchronize];
}
3驰吓、這里說一下signUser
屬性變量
在這里我將LoginService
做了一個單例,因為這里面的signUser
會在項目中其他地方用到,所以這里我使用了懶加載矮瘟。在懶加載中先判斷有沒有登錄狀態(tài)的記錄遵湖,如果有的話直接從本地里面取出signUser
。沒有的話給signUser
進行初始化偎蘸,具體見下面代碼:
這里也有一個點:從本地取出之前存儲的model對象庄蹋。在這里操作的時候先將
[userDefault objectForKey:SIGNUSERINFO]
轉(zhuǎn)換為NSData
,然后使用NSKeyedUnarchiver
解檔成UserInfoModel
。如下代碼:
- (UserInfoModel *)signUser {
if (!_signUser) {
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
if ([[userDefault objectForKey:ISLOGIN] isEqualToString:@"ISLOGIN"]) {
NSData *signUserData = [userDefault objectForKey:SIGNUSERINFO];
_signUser = (UserInfoModel *)[NSKeyedUnarchiver unarchiveObjectWithData:signUserData];
} else {
_signUser = [[UserInfoModel alloc] init];
}
}
return _signUser;
}
二迷雪、AppDelegate
在APPDelegate中限书,判斷本地是否有存儲的ISLOGIN
標(biāo)識,進行不同邏輯的跳轉(zhuǎn)章咧。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
BOOL isLogin = [[userDefault objectForKey:@"ISLOGIN"] isEqualToString:@"ISLOGIN"];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[UIViewController new]];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
if (isLogin) {
HomePageVC *vc = [[HomePageVC alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
} else {
LoginVC *vc = [[LoginVC alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
nav.navigationBarHidden = YES;
self.window.rootViewController = nav;
}
return YES;
}
三倦西、SettingVC
在這個界面點擊退出登錄按鈕執(zhí)行如下方法:
在這里最后不要用push或pop來切換界面。采用直接改變[UIApplication sharedApplication].keyWindow.rootViewController
的方法赁严。
[self.viewModel logout];
LoginVC *vc = [[LoginVC alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
[UIApplication sharedApplication].keyWindow.rootViewController = nav;
總結(jié)
以上就是登錄->退出登錄的核心邏輯,在此基礎(chǔ)上再添加別的業(yè)務(wù)邏輯疼约。比如啟動頁卤档,引導(dǎo)頁之類的。