之前一個ios項目中,需要通過UIWebview來打開一個靜態頁面,並在靜態頁面中
調用相關object-c代碼。
關於如何使用javascript調用object-c中的函數和方法,我搜索了好久
網上所有的方法,基本都指明了一個方向,那就是在UIWebview中載入的js代碼中
通過改變document.locations=“”,然後回調UIWebview的
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
函數,在上面這個函數中,通過截取NSURLRequest解析js中傳遞過來的參數,再根據參數
來選擇早已定義好的方法。
有沒有別的方法呢? 我找了幾個月,沒找到!但是有一個轉機。
我偶然知道了 javascriptCore.framework 這個庫
於是事情有了轉機。
二、在js中直接調用oc的方法
廢話不多說,現在看看如何在UIWebView的javascript中調用oc的方法
首先在建立一個UIWebView,代碼如下:
// // webview.m // login // // Created by wangdan on 15-3-19. // Copyright (c) 2015年 wangdan. All rights reserved. // #import "webview.h" #import@implementation webview -(id)initWithFrame:(CGRect)frame { self=[super initWithFrame:frame]; if( self ){ self.webview=[[UIWebView alloc]initWithFrame:CGRectMake(0, 310, self.bounds.size.width, 300)]; self.webview.backgroundColor=[UIColor lightGrayColor]; NSString *htmlPath=[[NSBundle mainBundle] resourcePath]; htmlPath=[htmlPath stringByAppendingPathComponent:@"html/index.html"]; NSURL *localURL=[[NSURL alloc]initFileURLWithPath:htmlPath]; [self.webview loadRequest:[NSURLRequest requestWithURL:localURL]]; [self addSubview:self.webview]; JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; context[@"log"] = ^() { NSLog(@"+++++++Begin Log+++++++"); NSArray *args = [JSContext currentArguments]; for (JSValue *jsVal in args) { NSLog(@"%@", jsVal); } JSValue *this = [JSContext currentThis]; NSLog(@"this: %@",this); NSLog(@"-------End Log-------"); }; // [context evaluateScript:@"log('ider', [7, 21], { hello:'world', js:100 });"]; } return self; } @end
(1)在上述代碼中,使用javascriptCore.framework,首先使用UIWebview加載一個靜態網頁,並
使用
JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
獲取該UIWebview的javascript執行環境。
(2)在該javascript執行環境中,定義一個js函數,注意關鍵點來了
這個函數的執行體完全是 objective-c代碼寫的,也就是下面:
context[@"jakilllog"] = ^() { NSLog(@"Begin Log"); NSArray *args = [JSContext currentArguments]; for (JSValue *jsVal in args) { NSLog(@"%@", jsVal); } JSValue *this = [JSContext currentThis]; NSLog(@"-------End Log-------"); };
(3)試想一下,在定義的webview中,如果使用js執行log這個函數,那麼會不會調用上面oc中block段代碼呢,答案是肯定的!
下面看看UIWebView 中所加載的 html及其js代碼是如何寫的
(4)index.html代碼
<script type="text/javascript" src="index.js"></script>
上面html定義了一個button,然後引用index.js,點擊button的響應函數為buttonClick()
該函數在index.js中定義,如下
function buttonClick() { jakilllog("hello world"); }
意思是點擊這個button,就調用jakilllog()函數,jakilllog()函數顯然是我們在oc中實現的一個block段,
就是上述綠色部分的block段。
點擊button會執行麼?答案是肯定的。
下面上圖
下圖是執行的結果
點擊html中的button,能夠執行oc中的代碼
說明直接從js調用oc的意圖達到。