webview與js互動
1.iOS呼叫js方法
- 先看下js的方法
function methodName(parameter) { alert(parameter); }
上面就是js的方法,methodName是方法名由iOS和js雙方約定,括號裡就是引數,傳什麼引數也是由雙方約定好的。
-
下面是iOS呼叫js的方法(共有兩種方法)
方法一:
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"methodName('%@')", parameter]];
webview:是你自己建立的UIWebview
methodName:js方法名
parameter:傳給js的引數
這個方法需要寫在webview載入完網頁後才會生效。如果網頁還沒載入完就呼叫這個方法去呼叫js的方法,那麼是調不到的。所以想在網頁剛載入的時候或者在載入途中就呼叫js方法傳參是不可能實現的。
這個方法比較適合給js傳些簡單的字串引數,陣列、字典、json字串、物件這些是傳不過去的。
如果js方法有多個引數,iOS在呼叫js方法傳參時多個引數用,隔開。例如:
js方法
function methodName(parameter1, parameter2) { alert(parameter1); }
iOS呼叫
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"methodName('%@','%@')", parameter1, parameter2]];
-
方法二(js方法就不寫了,跟上面一樣的)
iOS呼叫
//獲取js上下文環境 JSContext * context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; JSValue * action = context[@"methodName"]; [action callWithArguments:@[parameter1, parameter2]];
methodName:js方法名
parameter1:引數1
parameter2:引數2
這個呼叫js的方法需要注意的是引數必須寫在數組裡

ios呼叫js方法.png
/*! @method @abstract Invoke a JSValue as a function. @discussion In JavaScript, if a function doesn't explicitly return a value then it implicitly returns the JavaScript value <code>undefined</code>. @param arguments The arguments to pass to the function. @result The return value of the function call. */ - (JSValue *)callWithArguments:(NSArray *)arguments;
大家可以看到這個方法要求的就是陣列。而並不是js要求傳陣列
這個方法也是不能傳oc的一些物件的,因為語法的不同所以js並不認識oc的物件,但是json是雙方都認識的,所以一些複雜的資料可以用json字串傳
2.js呼叫iOS
-
1.最簡單直接的方法是攔截url
先看下js端是怎麼寫的
window.location.href = 'methodName://';
methodName:// 這個是ios和js雙方自己商量好的。這個是把http://改成了methodName://,當然//後面也可以有別的內容,這個就是看你們雙方是怎麼定的了。
ios端攔截url並做一些相應的操作
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ //獲取url NSString * requestStr = request.URL.absoluteString; NSLog(@"URL:%@",requestStr); //request.URL.scheme協議頭就是methodName if ([request.URL.scheme isEqualToString:@"methodName"]){ return NO; } return YES; }
上面這個方法是webview的一個代理方法。webview在開始載入網頁的時候都會走這個方法,在這個方法裡可以獲取到網頁的url。js的window.location.href = 'methodName://'這個方法就是網頁載入url的方法,所以js一執行這個方法ios這邊的方法就能攔截到。
在方法中需返回YES和NO,如果返回YES則網頁繼續載入,否則就不載入。因為methodName://這個url是錯誤的,我們只是想通過這個呼叫oc而不是真的去載入這個錯誤的url所以在攔截到了methodName://後返回NO。
上面oc方法中
NSString * requestStr = request.URL.absoluteString;
NSLog(@"URL:%@",requestStr);
這個是獲取url
if ([request.URL.scheme isEqualToString:@"methodName"]){
//這裡做oc相應的操作
return NO;
}
這個是根據協議頭來判斷是不是methodName://
- 2.js呼叫iOS方法二
// 獲取webview上的js JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // methodName是方法名 context[@"methodName"] = ^(){ NSArray *args = [JSContext currentArguments];//js傳過來的引數 NSLog(@"第一個引數=%@",[args[0] toString]); NSLog(@"第二個引數=%@",[args[1] toString]); dispatch_async(dispatch_get_main_queue(), ^{ //oc做相應的操作 }); };
這個方法寫在哪裡呢?
- 只要網頁載入完以後呼叫都是可以的。當然最好是寫在-(void)webViewDidFinishLoad:(UIWebView *)webView這個方法裡
上面這個是oc註冊方法給js呼叫,方法名就是methodName。
NSArray *args = [JSContext currentArguments];是js傳過來的引數,js那邊傳過來的不是陣列,而是這個[JSContext currentArguments]方法把引數轉化成了陣列。下面先看下js是怎麼呼叫的,就是知道引數是怎麼回事了。
methodName(parameter1, parameter2);
這個就是js呼叫oc的方法,methodName是方法名,parameter1和parameter2是兩個引數,引數是雙方定好的,可以傳一個引數也可以多個,多個引數就用,隔開。
js端傳的是這兩個引數,但在oc端接收的時候卻是以陣列形式接受的NSArray *args = [JSContext currentArguments];
所以args陣列中args[0]就是第一個引數。但是args裡包含元素是JSValue,並不是oc中的字串什麼的,所以還得轉化一下。
轉化為字串:[args[0] toString]
下面是轉化為各種型別的方法
- (id)toObject; /*! @method @abstract Convert a JSValue to an Objective-C object of a specific class. @discussion The JSValue is converted to an Objective-C object of the specified Class. If the result is not of the specified Class then <code>nil</code> will be returned. @result An Objective-C object of the specified Class or <code>nil</code>. */ - (id)toObjectOfClass:(Class)expectedClass; /*! @method @abstract Convert a JSValue to a boolean. @discussion The JSValue is converted to a boolean according to the rules specified by the JavaScript language. @result The boolean result of the conversion. */ - (BOOL)toBool; /*! @method @abstract Convert a JSValue to a double. @discussion The JSValue is converted to a number according to the rules specified by the JavaScript language. @result The double result of the conversion. */ - (double)toDouble; /*! @method @abstract Convert a JSValue to an <code>int32_t</code>. @discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. @result The <code>int32_t</code> result of the conversion. */ - (int32_t)toInt32; /*! @method @abstract Convert a JSValue to a <code>uint32_t</code>. @discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. @result The <code>uint32_t</code> result of the conversion. */ - (uint32_t)toUInt32; /*! @method @abstract Convert a JSValue to a NSNumber. @discussion If the JSValue represents a boolean, a NSNumber value of YES or NO will be returned. For all other types the value will be converted to a number according to the rules specified by the JavaScript language. @result The NSNumber result of the conversion. */ - (NSNumber *)toNumber; /*! @method @abstract Convert a JSValue to a NSString. @discussion The JSValue is converted to a string according to the rules specified by the JavaScript language. @result The NSString containing the result of the conversion. */ - (NSString *)toString; /*! @method @abstract Convert a JSValue to a NSDate. @discussion The value is converted to a number representing a time interval since 1970 which is then used to create a new NSDate instance. @result The NSDate created using the converted time interval. */ - (NSDate *)toDate; /*! @method @abstract Convert a JSValue to a NSArray. @discussion If the value is <code>null</code> or <code>undefined</code> then <code>nil</code> is returned. If the value is not an object then a JavaScript TypeError will be thrown. The property <code>length</code> is read from the object, converted to an unsigned integer, and an NSArray of this size is allocated. Properties corresponding to indicies within the array bounds will be copied to the array, with JSValues converted to equivalent Objective-C objects as specified. @result The NSArray containing the recursively converted contents of the converted JavaScript array. */ - (NSArray *)toArray; /*! @method @abstract Convert a JSValue to a NSDictionary. @discussion If the value is <code>null</code> or <code>undefined</code> then <code>nil</code> is returned. If the value is not an object then a JavaScript TypeError will be thrown. All enumerable properties of the object are copied to the dictionary, with JSValues converted to equivalent Objective-C objects as specified. @result The NSDictionary containing the recursively converted contents of the converted JavaScript object. */ - (NSDictionary *)toDictionary;
3.oc呼叫js window.close方法
- 先在webview載入完全的方法裡註冊下js
// webview載入完畢 -(void)webViewDidFinishLoad:(UIWebView *)webView{ //將window.close轉為back://當js呼叫window.close時自動呼叫back:// NSString *js = @"window.close = function() {window.location.assign(\"back://\");};"; [webView stringByEvaluatingJavaScriptFromString:js]; }
將window.close轉為back:// 當js呼叫window.close時自動呼叫back://,所以在代理方法中可以攔截到back://,然後再做相應的操作