iOS原生與H5交互WKWebView


一、原生與H5頁面交互方式

  1. 登陸后將token放入wkwebview的cookie中。以后wkwebview也可以同步原生app的登陸狀態了。

以下代碼   @"document.cookie = 'UID=%@';document.cookie = 'CLIENT=App';document.cookie = 'TOKEN=%@'" 根據自己項目的cookie格式傳遞。

 

 1     NSString *js = @"function clearCache(){localStorage.setItem('fundType',null);localStorage.setItem('fundTypeIndex',null);}clearCache();";
 2     NSString *cookie =
 3     [NSString stringWithFormat:@"document.cookie = 'UID=%@';document.cookie = 'CLIENT=App';document.cookie = 'TOKEN=%@'",
 4      [USER_DEFAULT objectForKey:KUSERUID] == nil ? @"":[USER_DEFAULT objectForKey:KUSERUID],[USER_DEFAULT objectForKey:KUSERTOKEN] == nil ?@"":[USER_DEFAULT objectForKey:KUSERTOKEN]];
 5     WKUserScript *cookieScript = [[WKUserScript alloc]
 6                                   initWithSource:cookie
 7                                   injectionTime:WKUserScriptInjectionTimeAtDocumentStart
 8                                   forMainFrameOnly:YES];
 9     [self.configuration.userContentController addUserScript:cookieScript];
10     [self reloadFromOrigin];

 

  2、審查wkwebview中的頁面元素,提取wkwebview登陸頁面中的登陸按鈕所調用的JS代碼(盡量向js開發人員要)

然后通過這句代碼執行js:把參數傳遞到js中。讓wkwebview執行js,wkwebview就登陸了。

以下代碼  @"function clearCache(){localStorage.setItem('fundType',null);localStorage.setItem('fundTypeIndex',null);}clearCache();" 是純js代碼,ios程序可以直接使用。

1 NSString *js = @"function clearCache(){localStorage.setItem('fundType',null);localStorage.setItem('fundTypeIndex',null);}clearCache();";
2             [self.baseWebView evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) {
3             }];

  3、通過該方法,截取H5頁面將要請求的頁面地址,來做原生相應的操作。這里可以讓wkwebview跳轉到“hello://uid=123_token=321”的方式來告訴原生,js傳了2個參數:uid=123  token=321(注意,這里是以hello開頭,可以寫成你們商量好的)然后通過:decisionHandler(WKNavigationActionPolicyCancel);

不讓wkwebview跳轉到“hello://uid=123_token=321”。去做我們真正要做的事情。

 1 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
 2     NSString *str = navigationAction.request.URL.absoluteString;//獲取當前正在請求的url
 4     if ([str isEqualToString:@"https://m.cgjr.com/"] && self.viewController.tabBarController.selectedIndex != 0) {
 5         decisionHandler(WKNavigationActionPolicyCancel);
 6         [self.viewController.tabBarController setSelectedIndex:0];
 7     }
 8     if ([str isEqualToString:@"https://m.cgjr.com/site/login.html"] && self.viewController.tabBarController.selectedIndex == 0) {
 9         decisionHandler(WKNavigationActionPolicyCancel);
10         UIStoryboard *sb = [UIStoryboard storyboardWithName:@"CGTZLogin" bundle:nil];
11         CGTZLoginViewController *navC = [sb instantiateViewControllerWithIdentifier:@"CGTZLoginViewController"];
12         navC.tabBarItem.title = @"登錄";
13         [self.viewController presentViewController:navC animated:YES completion:^{
14         }];
15         [self.viewController.tabBarController setSelectedIndex:0];
16     }
17     if ([str isEqualToString:@"https://m.cgjr.com/site/login.html"] && self.viewController.tabBarController.selectedIndex == 1) {
18         decisionHandler(WKNavigationActionPolicyCancel);
19         UIStoryboard *sb = [UIStoryboard storyboardWithName:@"CGTZLogin" bundle:nil];
20         CGTZLoginViewController *navC = [sb instantiateViewControllerWithIdentifier:@"CGTZLoginViewController"];
21         navC.tabBarItem.title = @"登錄";
22         [self.viewController presentViewController:navC animated:YES completion:^{
23         }];
24         [self.viewController.tabBarController setSelectedIndex:1];
25     }
26     if ([str isEqualToString:@"https://m.cgjr.com/site/login.html"] && self.viewController.tabBarController.selectedIndex == 2) {
27         decisionHandler(WKNavigationActionPolicyCancel);
28         UIStoryboard *sb = [UIStoryboard storyboardWithName:@"CGTZLogin" bundle:nil];
29         CGTZLoginViewController *navC = [sb instantiateViewControllerWithIdentifier:@"CGTZLoginViewController"];
30         navC.tabBarItem.title = @"登錄";
31         [self.viewController presentViewController:navC animated:YES completion:^{
32         }];
33         [self.viewController.tabBarController setSelectedIndex:2];
34     }
35     decisionHandler(WKNavigationActionPolicyAllow);
36 }

   4、在IOS平台上使用js直接調用OC方法

在Cocos2d-JS v3.0 RC2中,與Android上js調用Java一樣,Cocos2d-JS也提供了在iOS和Mac上js直接調用Objective-C的方法,示例代碼如下:

    var ojb = jsb.reflection.callStaticMethod(className, methodNmae, arg1, arg2, .....); 

jsb.reflection.callStaticMethod方法中,我們通過傳入OC的類名,方法名,參數就可以直接調用OC的靜態方法,並且可以獲得OC方法的返回值。

  • 參數中的類名,只需要傳入OC中的類名即可,與Java不同,類名並不需要路徑。比如你在工程底下新建一個類NativeOcClass,只要你將他引入工程,那么他的類名就是NativeOcClass,你並不需要傳入它的路徑。
1 import <Foundation/Foundation.h>
2     @interface NativeOcClass : NSObject
3     +(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content;
4     @end

方法

  • js到OC的反射僅支持OC中類的靜態方法。
  • 方法名比較要需要注意,我們需要傳入完整的方法名,特別是當某個方法帶有參數的時候,你需要將他的**:**也帶上。根據上面的例子。此時的方法名字是**callNativeUIWithTitle:andContent:**,不要漏掉了他們之間的**:**。
  • 如果是沒有參數的函數,那么他就不需要**:**,如下代碼,他的方法名是callNativeWithReturnString,由於沒有參數,他不需要**:**,跟OC的method寫法一致。

 

 1 +(NSString *)callNativeWithReturnString; 

使用示例

  • 下面的示例代碼將調用上面NativeOcClass的方法,在js層我們只需要這樣調用:
1     var ret = jsb.reflection.callStaticMethod("NativeOcClass", 
2                                                "callNativeUIWithTitle:andContent:", 
3                                                "cocos2d-js", 
4                                                "Yes! you call a Native UI from Reflection");

 

  • 這里是這個方法在OC的實現,可以看到是彈出一個native的對話框。並把titlecontent設置成你傳入的參數,並返回一個boolean類型的返回值。
1     +(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content{
2         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:content delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
3         [alertView show];
4         return true;
5     }

 

  • 此時,你就可以在ret中接受到從OC傳回的返回值(true)了。

注意

在OC的實現中,如果方法的參數需要使用float、int、bool的,請使用如下類型進行轉換:

  • float,int 請使用NSNumber類型
  • bool請使用BOOL類型。
  • 例如下面代碼,我們傳入2個浮點數,然后計算他們的合並返回,我們使用NSNumber而不是int、float去作為參數類型。
1 +(float) addTwoNumber:(NSNumber *)num1 and:(NSNumber *)num2{
2     float result = [num1 floatValue]+[num2 floatValue];
3     return result;
4 }

 

  • 目前參數和返回值支持 int, float, bool, string,其余的類型暫時不支持。

  5、wkwebview獨有,跟uiwebview的  jscontext 相似的 WKScriptMessage

js端這樣調用:紅色部分

 1 function onLoaded(){
 2         changeImageSrc();
 3     var allImage = document.getElementsByClassName("img-cache");
 4         allImage = Array.prototype.slice.call(allImage, 0);
 5         var imageUrlsArray = new Array();
 6         allImage.forEach(function(image) {
 7             var esrc = image.getAttribute("esrc");
 8             if(esrc){
 9             var newLength = imageUrlsArray.push(esrc);
10             }
11         });
12         window.webkit.messageHandlers.XXXApp.postMessage({"key":"getImageUrlArr","getImageUrlArr":imageUrlsArray});
13 
14 }onLoaded();

 

創建wkwebview時候:

 1         WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
 2         configuration.selectionGranularity = WKSelectionGranularityCharacter;
 3         configuration.userContentController   = userVC;
 4         [configuration.userContentController addScriptMessageHandler:self name:@"XXXApp"];//這里是iOS端的標識符  5         WKWebView * webView                   = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, kSCreenWidth, kSCreenHeight-64) configuration:configuration];
 6         webView.navigationDelegate            = self;
 7         webView.UIDelegate                    = self;
 8         NSURL *url                            = [NSURL URLWithString:self.urlString];
 9         NSMutableURLRequest *request          = [[NSMutableURLRequest alloc]initWithURL:url];
10         [webView loadRequest:request];

需要實現的代理方法:

 1 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
 2     NSDictionary *dataDic = message.body;
 3     if ([dataDic[@"key"] isEqualToString:@"getImageUrlArr"]) {//根據key的鍵值對,判斷調用哪一段代碼  4         NSArray *imageArr = dataDic[@"getImageUrlArr"];
 5         if (imageArr != nil) {
 6 // js傳過來的數組我們已經拿到了!,去做你想做的!
 7         }
 8     }
 9     if ([dataDic[@"key"] isEqualToString:@"imageDidClicked"]) {
10 //        [self imageDidClicked:dataDic[@"imageDidClicked"]];
11     }
12     if ([dataDic[@"key"] isEqualToString:@"imagesDownloadComplete"]) {
13     }   
19 }

 wkwebview相關參考資料:http://www.henishuo.com/wkwebview-js-h5-oc/

          (swift)http://www.henishuo.com/wkwebview-js/

WKWebView所有相關的類的API漢化: http://www.henishuo.com/wkwebview-objc/

以上一共5種交互方式,總有一種適合你。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM