很早之前有個(gè)項(xiàng)目牽扯到這塊就很想寫篇博客記錄下這篇文章了,這陣子有個(gè)項(xiàng)目又剛好遇到,正好有空,記錄記錄。
跟web的同鞋打過(guò)交道的肯定都知道,只要是涉及雙端交互就兩種方案啦。
截取鏈接,一般也就通過(guò)UIWebView回調(diào)代理
shouldStartLoadWithRequest截取固定鏈接然后在原生里面做相應(yīng)的業(yè)務(wù)操作,實(shí)現(xiàn)也比較簡(jiǎn)單,當(dāng)然這個(gè)方案也是一般涉及業(yè)務(wù)簡(jiǎn)單時(shí)候可以用,比如給個(gè)固定鏈接跳轉(zhuǎn)原生界面,如果業(yè)務(wù)復(fù)雜點(diǎn)web要給原生傳遞參數(shù)或者多個(gè)參數(shù)再或者原生要操作web里面的相關(guān)業(yè)務(wù),那就得考慮下面的方案二了。JS交互,iOS7以前我們對(duì)JS的操作只有webview里面一個(gè)函數(shù)
stringByEvaluatingJavaScriptFromString,當(dāng)然也有很多人是用的這個(gè)第三方JavascriptBridge,IOS7之后,蘋果可能也考慮到了這方面的需求,也很給力推出了JavaScriptCore這個(gè)框架。
通過(guò)stringByEvaluatingJavaScriptFromString 實(shí)現(xiàn)OC執(zhí)行JS代碼
stringByEvaluatingJavaScriptFromString 這個(gè)方法是UIWebView里面的方法,也是最為簡(jiǎn)單的和JS交互的方式。
-(nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
用法比較簡(jiǎn)單,一般在代理方法- (void)webViewDidFinishLoad:(UIWebView*)webView中使用。
- (void)webViewDidFinishLoad:(UIWebView*)webView
{
// 獲取當(dāng)前頁(yè)面的title
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
// 獲取當(dāng)前頁(yè)面的url
NSString *url = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
}
JavaScriptCore
這是IOS7后蘋果推出了JavaScriptCore這個(gè)框架,讓原生和web界面交互非常方便了。代碼是開源的JavaScriptCore 可以下載下來(lái)看看。
我們先了解下里面常見(jiàn)的屬性和協(xié)議
- JSContext:給JavaScript提供運(yùn)行的上下文環(huán)境,通過(guò)-evaluateScript:方法就可以執(zhí)行一JS代碼。
- JSValue:JavaScript和Objective-C數(shù)據(jù)和方法的橋梁,封裝了JS與ObjC中的對(duì)應(yīng)的類型,以及調(diào)用JS的API等。
- JSManagedValue:管理數(shù)據(jù)和方法的類JSVirtualMachine:處理線程相關(guān),使用較少。
- JSExport:這是一個(gè)協(xié)議,如果JS對(duì)象想直接調(diào)用OC對(duì)象里面的方法和屬性,那么這個(gè)OC對(duì)象只要實(shí)現(xiàn)這個(gè)JSExport協(xié)議就可以了。
OC調(diào)JS
self.context = [[JSContext alloc] init];
[self.context evaluateScript:@"function reduce(a,b) {return a-b}"];
JSValue *value = [self.context[@"reduce"] callWithArguments:@[@10, @3]];
NSLog(@"---%@", @([value toInt32])); //---7
JS調(diào)OC
JS調(diào)用OC有兩個(gè)方法:block和JSExport protocol。
html實(shí)現(xiàn)代碼
<input type="button" value="JS調(diào)用原生block實(shí)現(xiàn)" onclick="alert('alert');" />
<input type="button" value="JS調(diào)用原生JSExport protocol實(shí)現(xiàn)" onclick="native.alert('alert');" />
oc實(shí)現(xiàn)代碼
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 打印JS異常
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
};
// 以 block 形式關(guān)聯(lián) JavaScript function
self.context[@"alert"] =
^(NSString *alertText)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:alertText message:nil delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
};
// 以 JSExport 協(xié)議關(guān)聯(lián) native 的方法
self.context[@"native"] = self;
}
當(dāng)前類需要聲明和實(shí)現(xiàn)JSExport協(xié)議
@protocol TestJSExport <JSExport>
-(void)alert:(NSString *)alertText;
@end
@interface JSCallOCViewController : UIViewController<TestJSExport>
@property (strong, nonatomic) JSContext *context;
@end
#pragma mark - JSExport Methods
-(void)alert:(NSString *)alertText
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:alertText message:nil delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
}
好啦,關(guān)于JavaScriptCore的基本介紹就是這樣了。
參考http://www.itdecent.cn/p/a329cd4a67ee