Native 開發 和 H5 ?誰優誰劣,不在這邊展開討論。目前的開發過程中經常會遇到 原生應用 和web 交互的 需求。接下來我們就聊聊吧。
需求點
首頁 運營一個活動,一個大轉盤,轉呀轉呀,送 各種禮品吶。一個人一天可以轉三次,分享到社交軟件增加一次抽獎機會。
開始
iOS 應用 和web 頁面交互 有以下 幾種方法:
1、挺有名的第三方框架 WebViewJavaScriptBridge
2、iOS7 之后自帶的 JavaScriptCore
3、據說還可以 攔截協議
第一種 和 第三種方法 這里就不詳細介紹了(其實是我不會?。。。?/p>
方法一 作為 一個 知名的第三方框架,肯定會有 其他同行小伙伴介紹的,
傳送門 :http://kittenyang.com/webview-javascript-bridge/
反正我也寫不過他!
我選擇方法二!
因為簡單...
JavaScriptCore框架
JSContext:給JavaScript提供運行的上下文環境
JSValue:JavaScript和Objective-C數據和方法的橋梁
JSManagedValue:管理數據和方法的類
JSVirtualMachine:處理線程相關
JSExport:一個協議,接下來會介紹到
直接看代碼
@interfaceTWWebViewController() <UIWebViewDelegate>
@property(nonatomic,strong)UIWebView*webView;
@property(nonatomic,strong)JSContext*jContext;
@property(nonatomic,strong)TWWebCallBackFunctionHelper*helper;
@end
考慮到 需求經常變化,我用 TWWebCallBackFunctionHelper 統一處理 OC 和 JS 制定的 方法。
- (void)viewDidLoad
{
[superviewDidLoad];
self.helper= [[TWWebCallBackFunctionHelperalloc]init];[self.viewaddSubview:self.webView];[self.webViewloadRequest:[NSURLRequestrequestWithURL:[NSURLURLWithString:self.webUrl]]];
}
加載 ?webView ?和生成 ?TWWebCallBackFunctionHelper 對象。
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView*)webView
shouldStartLoadWithRequest:(NSURLRequest*)request
navigationType:(UIWebViewNavigationType)navigationType
{
returnYES;
}
- (void)webViewDidStartLoad:(UIWebView*)webView
{
if(!_jContext) {
self.jContext=
[webViewvalueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jContext[@"toApp"] =_helper;
}
}
- (void)webViewDidFinishLoad:(UIWebView*)webView
{
if(!self.webTitle.length) {
//獲取當前頁面的title
NSString*webTitle = [webViewstringByEvaluatingJavaScriptFromString:@"document.title"];
self.title= webTitle;
}
}
- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
{
NSLog(@"didFailLoadWithError = %@", error);
}
在 webView 開始加載的時候 獲取 JavaScript 上下文,和前端的小伙伴約定 toApp 為回調對象名(也有一些叫法 橋梁對象 ),helper 為實現協議對象。
接下來實現 TWWebCallBackFunctionHelper
#import <JavaScriptCore/JavaScriptCore.h>
@protocol webViewJsDelegate<JSExport>
JSExportAs(sharered, -(void)sharered
: (NSString *)url shareContent
: (NSString *)content linkUrl
: (NSString *)lUrl);
@end
JSExport 是 一個 協議, 自定義的 ?webViewJsDelegate 協議 需要遵守此協議。
我們來看下 ?JSExportAs 宏定義
PropertyName ?類似 一個 key,和 對應的 例子里是 sharered,其 對應 要實現的方法是
-(void)sharered:shareContent:linkUrl;其中 'key' 對應的 sharered 需要和 web 約定一致。
//遵守 webViewJsDelegate 協議
@interfaceTWWebCallBackFunctionHelper() <webViewJsDelegate>
@end
@implementationTWWebCallBackFunctionHelper
- (void)sharered:(NSString*)url shareContent:(NSString*)content linkUrl:(NSString*)lUrl
{
//TODO:
//實現業務邏輯,調起 分享 功能
}
@end
好了,差不多就這樣了,在運行過程中,偶現一個bug,點擊分享 按鈕沒有 絲毫 反應,也就是 分享UI組件 沒有 調用起來。這是什么鬼呀!
好吧,直接斷點 調試,-(void)sharered:shareContent:linkUrl 方法是跑到了,也就是 調用 UI 時沒有 反應??紤]是不是線程問題,看了JavaStript 相關定義,果然,“avaScript引擎是單線程運行的”,“JavaStript調用本地方法是在子線程中執行的” ,so...
- (void)sharered:(NSString*)url shareContent:(NSString*)content linkUrl:(NSString*)lUrl
{
//TODO:
//實現業務邏輯,調起 分享 功能
//主線程中去 刷新 UI 等功能
dispatch_async(dispatch_get_main_queue(), ^{
}
});
}
結論
這邊只是簡單的介紹 JavaScriptCore ?最基礎的 用法,很輕量。更多的 JavaScriptCore API 可以去查 蘋果官方文檔。另外在網上搜了下,發現一篇 類似 介紹 OC WebView 與JavaScript 交互 文章,除了 介紹JavaScriptCore ?還介紹了 iOS8之后的WKWebView ?和 第三點 攔截協議,介紹的都 比我 的詳細,貼出來 給大家參考:http://www.lxweimin.com/p/f896d73c670a?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weibo