本文只是介紹簡單的OC與JS交互
一、OC調用JS
<html> <header> <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8"/> <title>zhaoName制作的網頁</title> </header> <script Type = "text/javascript"> function login() { return 100; } </script> <body> 電話:10086 <button style="background:red; width:120px; height:30px;">call</button> </body></html>調用webView的方法
// 獲取網頁的標題self.title = [webView stringByEvaluatingJavascriptFromString:@"document.title"];// 調用JS中的函數NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"login();"]);該方法返回一個字符串,注意它是一個同步方法,若使用它執行非常耗時的操作會導致界面的卡頓。有兩個解決方案: 1>使用官方推薦webView方法evaluateJavaScript:completionHandler: 2>自定義一個延遲執行方法來防止阻塞,或將方法放到setTimeout 中

二、JS調用OC
<html> <header> <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8"/> <title>zhaoName制作的網頁</title> </header> <script Type = "text/javascript"> function login() { location.href = 'zhaoName://openLibrary'; } </script> <body> 電話:10086 <button style="background:red; width:120px; height:30px;" onclick="login();">call</button> <br> <a >zhaoName的Git</a> </body></html>以下都是點擊webView上的按鈕”call”,調用OC中的方法
1、沒有參數
/** * 通過這個方法完成JS調OC */- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSString *url = @"zhaoname://"; if ([request.URL.absoluteString hasprefix:url]) { NSString *methodName = [request.URL.absoluteString substringFromIndex:url.length]; [self performSelector:NSSelectorFromString(methodName) withObject:nil]; return NO; } NSLog(@"想加載網絡請求,不想做JS調用OC"); return YES;}- (void)openLibrary{ NSLog(@"JS調用OC方法--%s", __func__);}
2、一個參數
上面HTML中函數修改為
function login(){ location.href = 'zhaoName://sendMessage_?How are you';}OC獲取的路徑path會自動刪除’:’,所以此處用’_’代替。參數用?分割。(實際開發中需要你和寫HTML的人共同制定JS調OC的規則)
/** * 通過這個方法完成JS掉OC */- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSString *url = @"zhaoname://"; if ([request.URL.absoluteString hasPRefix:url]) { // 路徑 NSString *path = [request.URL.absoluteString substringFromIndex:url.length]; NSArray *subPaths = [path componentsSeparatedByString:@"?"]; // 獲取方法名 NSString *methodName = [subPaths.firstObject stringByReplacingOccurrencesOfString:@"_" withString:@":"]; // 參數 NSString *para = subPaths.lastObject; [self performSelector:NSSelectorFromString(methodName) withObject:para]; return NO; } NSLog(@"想加載網絡請求,不想做JS調用OC"); return YES;}- (void)sendMessage:(NSString *)message{ NSLog(@"JS調用OC方法--%s 參數:%@", __func__, message);}
3、兩個參數
上面HTML中函數修改為
function login(){ location.href = 'zhaoName://sendMessage_sendName_?hehe&zhaoName';}‘:’用’_’代替,方法名和參數用’?’分割,參數之間用’&’分割
/** * 通過這個方法完成JS掉OC */- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSString *url = @"zhaoname://"; if ([request.URL.absoluteString hasPrefix:url]) { // 路徑 NSString *path = [request.URL.absoluteString substringFromIndex:url.length]; NSArray *subPaths = [path componentsSeparatedByString:@"?"]; // 獲取方法名 NSString *methodName = [subPaths.firstObject stringByReplacingOccurrencesOfString:@"_" withString:@":"]; // 參數 NSArray *paras = nil; // 防止出現無參數的情況 if(subPaths.count == 2 || [subPaths.lastObject containsString:@"&"]) { paras = [subPaths.lastObject componentsSeparatedByString:@"&"]; } // 防止出現參數為空的情況 NSString *firstPara = paras.firstObject; NSString *secondPara = paras.count <= 1 ? nil : paras.lastObject; [self performSelector:NSSelectorFromString(methodName) withObject:firstPara withObject:secondPara]; return NO; } NSLog(@"想加載網絡請求,不想做JS調用OC"); return YES;}- (void)sendMessage:(NSString *)message sendName:(NSString *)sendName{ NSLog(@"JS調用OC方法--%s 參數:%@ %@", __func__, message, sendName);}
4、三個及以上的參數
系統自帶的方法performSelector最多只能傳兩個參數,所以有三個及以上的參數我們要借助NSInvocation類。
NSObject+Invocation.h文件
#import <Foundation/Foundation.h>@interface NSObject (Invocation)/** * 基于NSObject封裝一個可用于JS調用OC方法的分類,適用于參數可有可無,可有多個 @param selector 方法名 @param parameters 參數 @return 返回值 */- (id)performSelector:(SEL)selector withParameters:(NSArray *)parameters;@endNSObject+Invocation.m文件
#import "NSObject+Invocation.h"@implementation NSObject (Invocation)- (id)performSelector:(SEL)selector withParameters:(NSArray *)parameters{ // 方法簽名 NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector]; if(signature == nil) return nil; // 利用NSIvocation可以包裝一次方法調用(設置方法調用者、方法名、參數、返回值) NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; // 設置方法調用者 invocation.target = self; // 設置方法名 invocation.selector = selector; // 設置方法參數 注意參數下標從2開始,0、1被系統占用 for(int i=0; i<parameters.count; i++) { id object = parameters[i]; if([object isKindOfClass:[NSNull class]]) continue; [invocation setArgument:&object atIndex:i+2]; } // 執行 [invocation invoke]; // 設置返回值 id returnValue = nil; // 兼顧沒有返回值的方法 if(signature.methodReturnLength != 0) { [invocation getReturnValue:&returnValue];// 說明此方法有返回值 } return returnValue;}@end上面HTML中函數修改為
function login(){ location.href = 'zhaoName://sendMessage_sendName_reviceName_?hehe&zhaoName&nicai';}/** * 通過這個方法完成JS掉OC */- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSString *url = @"zhaoname://"; if ([request.URL.absoluteString hasPrefix:url]) { // 路徑 NSString *path = [request.URL.absoluteString substringFromIndex:url.length]; NSArray *subPaths = [path componentsSeparatedByString:@"?"]; // 獲取方法名 NSString *methodName = [subPaths.firstObject stringByReplacingOccurrencesOfString:@"_" withString:@":"]; // 參數 NSArray *paras = [subPaths.lastObject componentsSeparatedByString:@"&"]; // 調用OC中的方法 并獲取返回值 NSString *result = [self performSelector:NSSelectorFromString(methodName) withParameters:paras]; NSLog(@"%@", result); return NO; } NSLog(@"想加載網絡請求,不想做JS調用OC"); return YES;}- (NSString *)sendMessage:(NSString *)message sendName:(NSString *)sendName reviceName:(NSString *)reviceName{ NSLog(@"JS調用OC方法--%s 參數:%@ %@ %@", __func__, message, sendName, reviceName); return @"發信息";}
新聞熱點
疑難解答