在实际开发中几乎所有的APP都会存在用户体系,假如没有涉及用户体系的APP,提交审核的时候有很大概率会被苹果爹地直接拒绝不允许上架。而有了用户体系,那么就肯定会存在登录以及保持登录的需求,要不然用户每次启动APP都得重新登录,那就乖乖了。保持登录状态的方式目前大致有以下几种方式:

一、利用Cookie机制实现

我们知道cookie是为了解决http无状态的一种技术,被电商、oa等web应用广泛使用。如果我们的App和后端通讯采用的http通讯方式,可以利用cookie技术进行登录状态保持。比如我们可以把sessionID和有效期保存在cookie中,发给前端App,前端App收到后保存在本地。当访问后端服务把sessionID和有效期作为参数传给后台进行认证。直到sessionID失效,用户都不需要重新登录。

二、本地保存用户名和密码

当用户第一次输入账号和密码的时候,APP端本地保存用户的账号和密码,下次启动的时候获取本地保存的账户和密码进行登录,由我们开发者在后台进行登录处理,不过这个有个不是太合适的就是相当于在APP本地保存了用户的这些信息,意义上来说不安全,不过大致的实现方式如下:

1、在登陆页面对应的类loginViewController.h中定义两个TextField和一个Button,用来接受用户输入的用户名和密码,点击按钮登陆,如果登陆成功,就将用户的登陆信息存放在UserDefault中,然后跳入主页面。

@interface LoginViewController ()

@property (nonatomic, strong) UITextField *username;

@property (nonatomic, strong) UITextField *password;

@end

2、在loginViewController.m中实现两个TextField和一个Button,直接实现按钮的点击登录事件:登录请求成功后,走成功回调,回调下面实现将用户名和密码存入UserDefault中,页面跳转到主页面。下面数据请求的代码略去了,直接上存储UserDefault代码,跳转主页面。

NSString *username = self.username.text;

NSString *password = self.password.text;

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

[userDefaults setObject:username forKey:@"username"];

[userDefaults setObject:password forKey:@"password"];

[userDefaults synchronize];

UITabBarController *tabBarVc = [[UITabBarController alloc] init];

UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tabBarVc];

AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

appdelegate.window.rootViewController = nc;

3、在AppDelegate.m中实现:用户第一次进入APP时自动进入登录注册页,提示用户注册登录,用户登录成功后才进入主页,再次进入APP时,不用再次登录就直接进到主页了

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//初始化Window

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

self.window.backgroundColor = [UIColor whiteColor];

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

if (![userDefaults objectForKey:@"username"]){

//进入主页

UITabBarController *tabbarVc = [[UITabBarController alloc]init];

UINavigationController *navVc = [[UINavigationController alloc]initWithRootViewController:tabbarVc];

self.window.rootViewController = navVc;

} else {

//进入登录页面

LoginViewController *loginVc = [[LoginViewController alloc] init];

[self.navController pushViewController:loginVc animated:YES];

}

[self.window makeKeyWindow];

return YES;

}

4、退出登录

//退出登录,清除用户信息

- (void)logout{

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

[userDefaults removeObjectForKey:@"username"];

[userDefaults removeObjectForKey:@"password"];

//跳转登陆页

LoginViewController *loginVc = [[LoginViewController alloc] init];

[self.navController pushViewController:loginVc animated:YES];

}

三、前后端配合采用token方式

token方式在app认证上用的比较普遍,App初始登录时,提交账号和密码数据给服务端,服务端根据定义的的策略生成一个token字符串,token字符串中可以包含用户信息、设备ID等信息以保证用户的唯一性,服务端并对token设置一定的期限。服务端把生成的token字符串传给客户端,客户端保存token字符串,并在接下来的请求中带上这个字符串。相对于在App本地token的安全性更高了。

说明:这里说说关于设备唯一ID的小细节,如果直接把设备唯一ID传给后台的话,这里可能会出现一个问题,比如在同一台手机退出登录后再登录其他账号,那么就会出现多个账号的设备ID就都一样了。这样会带来什么后果呢?比如如果还使用极光推送的话,用这个设备ID注册别名的话,那么就会出现多个账号的别名都是一样的,那么推送就乱了。

//uuid + 手机 + iOS

NSString *uuid = [[GetUUID getUUID] stringByReplacingOccurrencesOfString:@"-" withString:@""];

//截取UUID的后十位

NSString *uuidPart = [uuid substringFromIndex:uuid.length - 10];

NSString *aliasStr = [NSString stringWithFormat:@"%@_%@_iOS",uuidPart,phoneNum];

上面就是我在实际开发使用设备ID唯一性的处理,就是UUID + 手机号码 + iOS(平台),安卓就是UUID + 手机号码 + Android。这样子就不仅避免了同一台设备登录多个账号的问题,还区分了不同平台登录的账号。

1、用户第一次登录之后本地保存token

[[NSUserDefaults standardUserDefaults] setObject:[responseObject.data objectForKey:@"token"] forKey:token];

[[NSUserDefaults standardUserDefaults] synchronize];

2、再次启动的时候获取本地保存的token

NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:token];

然后用这个token请求一个后台验证该token是否在有效期的接口,接着根据后台返回的信息进行相关页面的跳转处理。

到此为止,目前几种保持登录状态的方法大致介绍完了,不知道细心的你有没有发现一个小细节,那就是很多都是采用根据登录状态是否有效来设置window的rootViewController根控制器,就是说没有登录状态下rootViewController是loginViewController登录页,有登录状态有效的情况下rootViewController是navVC导航控制器或者其他UIViewController控制器等,如下:

if(有登录状态){

BaseTabBarViewController *baseVc = [[BaseTabBarViewController alloc] init];

self.window.rootViewController = baseVc;

}else{

LoginViewController *loginVc = [[LoginViewController alloc] init];

self.window.rootViewController = loginVc;

}

但是有一种比较特殊的情况,其实也不特殊,就是也是一种产品形式,那就是不管有没有登录状态下,window的rootViewController都是BaseTabBarViewController,就是说不会随着登录状态失效根控制器进行更换,因为很多APP也都存在游客模式,就是不用登录状态也可以进入APP进行基础的操作,而当点击到需要登陆地方时没有登录状态的话就跳转到登录页,有的话就继续下一步操作,那么这个时候我们应该怎么处理呢?下面继续说说暂时个人想到的处理方式:

处理方式1:

首先设置window的rootViewController根控制器为BaseViewController(UIViewController类型的),然后再立即获取用户的登录状态是否有效,不管登录状态是否有效都会把window的rootViewController设置为BaseTabBarViewController,只是在获取到用户登录状态信息之后BaseTabBarViewController里的有些UI展示不一样,直接上代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//token登录

[self initService];

//先创建根控制器,然后会在AppDelegate+AppService分类中进行根控制器的替换

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

//先进行网络监测防止手机开启飞行模式时进入白屏

if (![XMFUserHttpHelper checkNetStatus]) {

XMFTabBarViewController *baseVc = [[XMFTabBarViewController alloc] init];

self.window.rootViewController = baseVc;

}else{

XMFBaseViewController *baseVc = [[XMFBaseViewController alloc] init];

self.window.rootViewController = baseVc;

}

[self.window makeKeyAndVisible];

}

//初始化服务

-(void)initService{

NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:token];

if (![sessionId isBlankString]) {//先判断是否是空字符串

//获取保存的token供下面接口的头部使用

[XMFGlobleManager getGlobleManager].token = token;

[SVProgressHUD show];

[[XMFUserHttpHelper sharedManager] sessionLoginCheckWithParam:nil success:^(XMFResponseModel *responseObject) {

[SVProgressHUD dismiss];

//token在有效期内

if (responseObject.returnCode == XMFHttpReturnCodeSuccess) {

token = [responseObject.data objectForKey:@"token"];

[XMFGlobleManager getGlobleManager].isLogin = YES;

//发送登录成功的通知

[[NSNotificationCenter defaultCenter] postNotificationName:DWQ_NOTIFY_LoginState_Change object:@YES userInfo:nil];

[[NSUserDefaults standardUserDefaults] setObject:[responseObject.data objectForKey:@"token"] forKey:token];

[[NSUserDefaults standardUserDefaults] synchronize];

[self setRootViewController];

}else{

[self setRootViewController];

//登录失败

[[NSNotificationCenter defaultCenter] postNotificationName:DWQ_NOTIFY_LoginState_Change object:@NO userInfo:nil];

}

} failure:^(NSError *error) {

[self setRootViewController];

}];

}else{

[self setRootViewController];

}

}

//等待验证token是否有效之后进行设置根控制器

-(void)setRootViewController{

XMFTabBarViewController *tabvc = [[XMFTabBarViewController alloc] init];

self.window.rootViewController = tabvc;

}

这样子大致就把不管有无登录状态rootViewController都为XMFTabBarViewController的情况处理好了,不过这里面还有一个小细节会影响体验,仔细看看上面是不是登录状态是否有效取决于后台返回,网络请求快的情况下可能感受不到,那万一网络请求缓慢的话,那就会出现用户会在等待AFHTTPSessionManager的manager.requestSerializer.timeoutInterval = 20;时间之后才出现了XMFTabBarViewController,这样的体验是有点影响的,那么再来继续优化一下。

处理方式2:

这里直接不管是否有登录状态都直接设置window的rootViewController为XMFTabBarViewController,代码如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//token登录

[self initService];

//先创建根控制器,然后会在AppDelegate+AppService分类中进行根控制器的替换

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

ZFTabBarViewController *baseVc = [[ZFTabBarViewController alloc] init];

self.window.rootViewController = baseVc;

[self.window makeKeyAndVisible];

}

//初始化服务

-(void)initService{

NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:token];

if (![sessionId isBlankString]) {//先判断是否是空字符串

//获取保存的token供下面接口的头部使用

[XMFGlobleManager getGlobleManager].token = token;

[SVProgressHUD show];

[[XMFUserHttpHelper sharedManager] sessionLoginCheckWithParam:nil success:^(XMFResponseModel *responseObject) {

[SVProgressHUD dismiss];

//token在有效期内

if (responseObject.returnCode == XMFHttpReturnCodeSuccess) {

token = [responseObject.data objectForKey:@"token"];

[XMFGlobleManager getGlobleManager].isLogin = YES;

//发送登录成功的通知

[[NSNotificationCenter defaultCenter] postNotificationName:DWQ_NOTIFY_LoginState_Change object:@YES userInfo:nil];

[[NSUserDefaults standardUserDefaults] setObject:[responseObject.data objectForKey:@"token"] forKey:token];

[[NSUserDefaults standardUserDefaults] synchronize];

}else{

//登录失败

[[NSNotificationCenter defaultCenter] postNotificationName:DWQ_NOTIFY_LoginState_Change object:@NO userInfo:nil];

}

} failure:^(NSError *error) {

}];

}

}

然后在会随着登录状态改变UI界面的页面进行对“isLogin”属性进行kvo监测,接着进行相应的UI改变,代码如下:

- (void)viewWillAppear:(BOOL)animated{

[super viewWillAppear:animated];

//增加对登录状态"isLogin"值变化的观察

kWeakSelf(self)

[JJKeyValueObserver addObserveObject:[XMFGlobleManager getGlobleManager] keyPath:@"isLogin" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew changeBlock:^(NSDictionary *dict) {

// DLog(@"登录状态发生了改变:%@",[dict description]);

weakself.rightLoginBtn.selected = [XMFGlobleManager getGlobleManager].isLogin;

}];

}

同时博主的kvo使用的是第三方JJKeyValueObserver,大家有需要的可以去GitHub上下载使用,也可以自己实现kvo,原理是一样的。那经过这么一番处理之后,整个保持登录的过程差不多就处理完了,同时博主开发中采用的是“前后端配合采用token方式”。

如果以上的分享帮助到你了,欢迎分享,更欢迎赞赏,也可以直接打开支付宝、微信、QQ的扫一扫功能直接扫下面的支付宝、微信、QQ三合一打赏码进行打赏支持作者创作,感谢感谢!

image

欢迎和我交流,QQ:834537795(小蜜蜂)

php和app保持登录状态,关于iOS开发者中APP保持登录状态的几种实现方式和一些思考...相关推荐

  1. app应用分发平台|苹果ios超级签名|APP封装打包|应用内测托管平台|iOS应用企业签名|Android应用上传内测-虾分发

    CDN分发平台-注册免审核-虾分发 https://xiafenfa.com/ app应用分发平台|苹果ios超级签名|APP封装打包|应用内测托管平台|iOS应用企业签名|Android应用上传内测 ...

  2. ios html5 app上架,H5封装的IOS应用上架App Store被拒怎么办

    原标题:H5封装的IOS应用上架App Store被拒怎么办 H5封装的IOS应用如果上要架到App Store几乎是无望,原因是苹果官方为了保证App Store应用商店上的APP优量和更好的体验, ...

  3. App Store生存法则:iOS开发者经验分享

    http://tech.it168.com/a2011/0301/1161/000001161591.shtml http://hi.baidu.com/solidmcp/blog 还不错 转载于:h ...

  4. 解决iOS开发中App启动广告的功能

    前不久有朋友需要一个启动广告的功能,我说网上有挺多的,他说,看的不是很理想.想让我写一个,于是乎,抽空写了一个,代码通俗易懂,简单的封装了一下,各种事件用block回调的,有俩种样式的广告,一种是全屏 ...

  5. VUE 表格中显示状态的列 颜色圆点+文字/颜色圆点+鼠标操作 两种表现方式

    鼠标悬停在色块上显示提示框 VUE代码(element-UI): <el-table-column prop="status" label="状态" he ...

  6. iOS项目中一定会用到的两种常用的弹框 从底部弹出 、中间弹出 Swift代码

    从底部弹出的弹框 ,样式如下 1.利用CocoaPods导入HWPanModal 框架,在桥接文件中导入头文件 #import "HWPanModal.h" 2.创建一个新的控制器 ...

  7. IOS研究之App转让流程须知具体介绍

     网络上有非常多开发人员提问怎么转让App并想知道具体的流程.实际上Appstore的App转让流程还是比較简单的.以下特酷吧依据自己的实际操作总结下iOS Appstore中App的转让流程.供 ...

  8. Cordova iOS 项目中微信/qq/Apple ID插件的安装以及登录的实现

    说明:我们在做项目的时候,往往会接入第三方登录,使用官方或者已经大神已经写好的插件,不仅节省时间,而且可以加快我们项目开发的进度,本文章记录我在工程中所用到的几个第三方登录,一方面为了防止时间长了忘记 ...

  9. iOS 如何向App Store提交应用

    当你克服重重困难终于开发出了自己的App,下一步就是向App Store提交应用了,这时应该如何操作呢?我的App真的准备好提交了?我敢肯定这些问题将会浮现在你的脑海.基于这篇教程,我将告诉你一个完整 ...

最新文章

  1. 更新pcb封装导入_教你如何将 AD 或 PADS 的原理图导入 Allegro 做 Layout
  2. NSString取子串
  3. 央行发布论文:区块链能做什么,不能做什么?
  4. Spring 梳理 - ContentNegotiatingViewResolver
  5. Shell脚本攻略02-玩转变量与环境变量
  6. 高性能必须有 多活塞卡钳
  7. pb 如何判断缺纸_如何快速判断是否低估?四种相对估值法应用精析
  8. 标准10进制公制度量系统中 倍率关系 大全
  9. 我们应该搞清楚分支预测
  10. 微课|中学生可以这样学Python(例4.7):定时器
  11. 文件粉碎机c语言代码,Life——文件粉碎机源码
  12. 蓝桥杯 ALGO-39 算法训练 数组排序去重
  13. Android AsyncTask示例教程
  14. error C2712: Cannot use __try in functions that require object unwinding
  15. 百度AI市场热品试用 | 迪威泰超薄双目摄像机模组
  16. canvas轨迹运动, 利用向量实现点匀速运动
  17. linux命令日志抓取,linux抓取某条日志记录的命令
  18. 刘彬20000词汇02
  19. 百度图片时看到一张很眼熟,竟然是自己发的,这收录效率!
  20. 华为ME909 4G LTE模块在树莓派+Ubuntu Mate平台的联网演示

热门文章

  1. GTK中g_signal_connect与g_signal_connect_swapped的区别
  2. 《VC++深入详解》第四章 简单绘图
  3. r语言lm函数找不到对象_错误:在R中找不到函数....
  4. iOS App转让流程须知详细介绍
  5. 第一章 1.2掌握Deluxe APP的剪辑功能
  6. 【小沐学Python】Python实现Web服务器(Ubuntu下调试Flask)
  7. PPmoney疑似出现延期兑付:或未真正剥离及贷,收取10%保证金借款年化利息60%
  8. 简单几步让你的 JS 写得更漂亮
  9. html中钟表功能的js插件,基于canvas的15种不同外观时钟js插件
  10. jQuery动态生成的元素如何绑定事件