JS和UIWebview通過JavaScriptCore無法執行iOS本地方法解決方案[轉載]

原著:https://galileioo.github.io/posts/UIWebview-JS.html

感謝原文作者提供這么好的文章!

------------------------正文如下------------------------

問題描述

html里面的script標簽里面需要在網頁加載的時候直接調用客戶端的方法。無法調用成功。

問題分析

之前也做過js通過UIWebview調用iOS端代碼。可以成功調用。但是為什么能夠成功調用? 因為我之前的做法是當頁面加載成功時候才去注入wap_obj,代碼如下。

#pragma mark - UIWebViewDelegate

- (void)webViewDidFinishLoad:(UIWebView *)webView {

self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

self.jsContext[@"wap_obj"] = self;

}

以前的使用場景是點擊webview上的按鈕,觸發js方法來調用iOS本地方法。因為點擊按鈕時候網頁已經加載完了。所以這個場景是ok的。

現在,新的場景是先加載js直接調用方法。調用方法在執行webViewDidFinishLoad之前。所以方法不觸發就是理所當然。

解決方案

在網上搜索良久,終于找到了一篇文章。JavaScript和Objective-C交互的那些事.里面用到了一個第三方庫。UIWebView-TS_JavaScriptContext. 參考此項目的寫法,將文件加入工程中之后就可以解決網頁加載中無法成功調用本地方法的問題。但是看到文章后面的一些評論說是有被拒的風險。然后去github看了下issue有如下被拒的原因.

I hope that we do not use this library, the bloody lessons.

2016年9月1日 上午1:22

發件人 Apple

Performance - 2.5.1

Your app uses or references the following non-public APIs:

“parentFrame”

The use of non-public APIs is not permitted on the App Store because it can lead to a poor user experience should these APIs change.

為了防止被拒。我還是放棄此種方法把。

但是上一種方法給出了一種思路。就是使用didCreateJavaScriptContext。這個方法會多次回調。以獲取最新的的JSContext。第一種方法只要不調用parentFrame方法不就好了?所以對之前方法加以修改就是改為發通知方式。方法代碼如下

#import "NSObject+JSContextTracker.h"@implementationNSObject(JSContextTracker)-(void)webView:(id)unuseddidCreateJavaScriptContext:(JSContext*)ctxforFrame:(id)alsoUnused{if(!ctx)return;[[NSNotificationCenterdefaultCenter]postNotificationName:@"LLCreatJSContex"object:ctx];}@end

在使用的地方添加觀測

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(creatJSContex:) name:@"LLCreatJSContex" object:nil];

-(void)dealloc

{

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LLCreatJSContex" object:nil];

}

-(void)creatJSContex:(NSNotification*)noti

{

NSLog(@"%@",noti);

//注意以下代碼如果不在主線程調用會發生閃退。

dispatch_async( dispatch_get_main_queue(), ^{

self.jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

self.jsContext[@"wap_obj"] = self;

self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {

context.exception = exceptionValue;

NSLog(@"異常信息:%@", exceptionValue);

};

});

}

運用這種思路。也可以實現成功調用。并且我們的應用已經通過審核。

參考

http://www.lxweimin.com/p/939db6215436

https://github.com/TomSwift/UIWebView-TS_JavaScriptContext

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 隨著H5技術的興起,在iOS開發過程中,難免會遇到原生應用需要和H5頁面交互的問題。其中會涉及方法調用及參數傳值等...
    Chris_js閱讀 3,120評論 1 8
  • 一、簡介 近兩年隨著HTML5的迅速發展與日趨成熟,越來越多的移動開發者選擇使用HTML5來進行混合開發,不僅節約...
    RainyGY閱讀 1,909評論 1 12
  • 跟原生開發相比,H5的開發相對來一個成熟的框架和團隊來講在開發速度和開發效率上有著比原生很大的優勢,至少不用等待審...
    大沖哥閱讀 1,866評論 0 7
  • iOS開發系列--網絡開發 概覽 大部分應用程序都或多或少會牽扯到網絡開發,例如說新浪微博、微信等,這些應用本身可...
    lichengjin閱讀 3,721評論 2 7
  • 終于,考完了。本來以為會長舒一口氣,預測到可能連差強人意都不如的成績讓我這口氣舒的并不順暢,這就是自以為已經很努力...
    垛垛閱讀 251評論 0 0