iOS H5免登錄,同步APP登錄狀態,OC和JS交互

需求分析

APP某個頁面嵌入H5頁面,當前H5頁面擁有登錄狀態。在此以前,用戶進入本頁面,即便用戶在登錄狀態,依然顯示未登錄,因此須要把APP的登錄狀態傳給H5,達到免登錄目的。html

下面的截圖是咱們APP的活動頁面前端

截圖

目前JS與OC相互調用的方式

目前主要的JS與OC相互調用方式主要有以下6種:web

  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端登錄信息作統一接口才能最終達到目的。)bash

好了廢話很少說,上代碼session

先建立webview而後進行偏好設置configurationide

- (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頁面的登錄按鈕進行攔截url

#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,不須要的能夠忽略spa

/**
 獲取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同步登錄需求啦!

相關文章
相關標籤/搜索