博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS H5免登陆,同步APP登陆状态,OC和JS交互
阅读量:7049 次
发布时间:2019-06-28

本文共 4527 字,大约阅读时间需要 15 分钟。

需求分析

APP某个页面嵌入H5页面,当前H5页面拥有登陆状态。在此之前,用户进入本页面,即使用户在登陆状态,依然显示未登陆,所以需要把APP的登陆状态传给H5,达到免登陆目的。

下面的截图是我们APP的活动页面

目前JS与OC相互调用的方式

目前主要的JS与OC相互调用方式主要有如下6种:

  1. 在JS 中做一次URL跳转,然后在OC中拦截跳转。(这里分为UIWebView 和 WKWebView两种,UIWebView兼容iOS 6)
  2. 利用WKWebView 的MessageHandler。
  3. 利用系统库JavaScriptCore,来做相互调用。(iOS 7推出)
  4. 利用第三方库WebViewJavascriptBridge。
  5. 利用第三方cordova库,以前叫PhoneGap。(这是一个库平台的库)
  6. 当下盛行的React Native。

初步考虑,App兼容iOS7选择JavaScriptCore方式,App只兼容iOS8以上,可以采用WKWebView,并使用MessageHandler方式。

因为我们前端H5采用的是把登陆状态token存放在session Storage里面,采用第二种方式是最简洁方便的。可能有些前端是从URL传登陆状态值的,那这种方式就更简单了,只要把请求URL拼接上APP登陆token(以上两种情况需要后端把APP和H5端登陆信息做统一接口才能最终达到目的。)

好了废话不多说,上代码

先创建webview然后进行偏好设置configuration

- (void)viewDidLoad {    [super viewDidLoad];    self.view.backgroundColor = UIColorFromRGB(0xf3f6f6);    //添加登陆通知,防止APP端未登陆状态,在后面的代理对h5登陆做拦截处理,回调原生APP的登陆方式,    //然后通过通知方式来重载本页面    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uerislogin) name:@"userIsLogin" object:nil];    JMUserInfoModel *userInfo = [JMLoginManager getInfo];//这是我的本地登陆信息        //进行偏好设置,把token传到session里面去。    WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc] init];    _userContent = [[WKUserContentController alloc] init];        //关键的地方来了,这一步是对session添加token信息,就算目前APP未登陆状态,传入空字符串也是没关系,    //后面通知重载页面会重新注入信息。    NSString * js = [NSString stringWithFormat:@"window.sessionStorage.setItem('token','%@')",userInfo.user_token];    WKUserScript * userScript = [[WKUserScript alloc]initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];    [_userContent addUserScript:userScript];    configuration.userContentController = _userContent;            //注意要在创建webview的时候就要把偏好设置给初始化configuration    _webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, DEVICE_WIDTH, DEVICE_HEIGHT- JMHeightGap) configuration:configuration];    _webView.backgroundColor = [UIColor whiteColor];    _webView.UIDelegate = self;    _webView.navigationDelegate = self;    [_webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL]; //添加观察者模式 更换标题        NSString *url = [NSString stringWithFormat:@"https://www.jumifinance.com/h5/views/wheel/wheel.html"];    NSURL *weburl =[[NSURL alloc] initWithString:url];    NSURLRequest *request =  [[NSURLRequest alloc] initWithURL:weburl];    [self.webView loadRequest:request];        [self.view addSubview:self.webView];}复制代码

在代理里面对H5页面的登陆按钮进行拦截

#pragma mark - UIWebViewDelegate-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{    NSString *url = [navigationAction.request.URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];        NSLog(@"请求拦截===== %@",url);    //对请求url进行字符串匹配,如果请求链接里有登陆请求,进行拦截    if ([url rangeOfString:@"common/login.html"].location != NSNotFound) {//UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"方式一" message:@"这是OC原生的弹出窗" delegate:self cancelButtonTitle:@"收到" otherButtonTitles:nil];//[alertView show];        //调用原生登陆接口        [[JMLoginManager shareLogin] loginAction];        decisionHandler(WKNavigationActionPolicyCancel);    }else    {        decisionHandler(WKNavigationActionPolicyAllow);    }    }复制代码

下面代码是修改title的kvo,不需要的可以忽略

/** 获取H5页面 当前页面的标题  @param keyPath key @param object  对象 @param change 。。 @param context 内容 */- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {    if ([keyPath isEqualToString:@"title"])    {        if (object == self.webView) {            self.title = self.webView.title;        }        else        {            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];        }    }    else {                [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];    }}复制代码

然后是通知的回调

-(void)uerislogin{    JMUserInfoModel *userInfo = [JMLoginManager getInfo];    NSString * js = [NSString stringWithFormat:@"window.sessionStorage.setItem('token','%@')",userInfo.user_token];    WKUserScript * userScript = [[WKUserScript alloc]initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];    [_userContent addUserScript:userScript];        [self.webView reload];}复制代码

最后记得在dealloc里面进行销毁通知和KVO

-(void)dealloc{    [_webView removeObserver:self forKeyPath:@"title"];    [[NSNotificationCenter defaultCenter] removeObserver:self];}复制代码

到这里已经实现了完美的APP H5同步登陆需求啦!

转载地址:http://wrpol.baihongyu.com/

你可能感兴趣的文章
摊上事了! Facebook向用户手机发生日信息涉嫌违法
查看>>
《HTML5 Canvas开发详解》——2.4 使用路径创建线段
查看>>
《Ansible权威指南》一2.2 Ansible配置文件解析
查看>>
linux常用命令 — 操作目录
查看>>
vue axios+springboot 文件下载
查看>>
JS的继承方式
查看>>
掘金广告产品介绍
查看>>
九宫格
查看>>
手把手教你写一个 VSCode 插件
查看>>
cookie和session
查看>>
使用 multipart/x-mixed-replace 实现 http 实时视频流
查看>>
史上最牛内推小组(持续更新)
查看>>
现实中的路由规则,可能比你想象中复杂的多
查看>>
nginx配置gzip中的坑
查看>>
Javascript中的函数声明与函数表达式
查看>>
Python学习笔记 - queue
查看>>
茶器漫谈 高逼格 or 真内涵?
查看>>
HTML5学习之Web Storage基础知识
查看>>
tab切换
查看>>
垃圾回收及内存调试工具的介绍
查看>>