JavaScript和Objective-c交互
- 現(xiàn)在的開發(fā)不再是純原生的開發(fā)了品抽,在很多APP中,很多活動頁面甜熔、或者說專題頁面圆恤,都采用了H5的頁面
- 這種方式的好處就是這些頁面可以很方便的修改,不用提交新的APP到AppStore去審核
- 那么js和oc的交互就分為:js調用oc方法腔稀、oc調用js方法 兩種情況
OC調用JS
-
stringByEvaluatingJavaScriptFromString
方法執(zhí)行js語句
// 執(zhí)行JS語句
[webView stringByEvaluatingJavaScriptFromString:@"alert(100);"];
// 利用JS獲得當前網(wǎng)頁的標題
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title;"];
// 執(zhí)行JS函數(shù)
[webView stringByEvaluatingJavaScriptFromString:@"login();"];
JS調用OC
這種模式有點麻煩盆昙,就是傳遞參數(shù)的問題
不傳遞參數(shù)、一個或者兩個參數(shù)焊虏,這些情況比較簡單
但是想傳遞多個參數(shù)淡喜,就比較麻煩了
-
思路:
- 1、在網(wǎng)頁中發(fā)送請求诵闭,如果是想調用OC方法炼团,那么就需要自定義協(xié)議頭
- 2、請求的地址需要自定義:協(xié)議頭和方法名還有參數(shù)的拼接需要定義好規(guī)則
- 3疏尿、在UIWebView的代理方法中攔截請求瘟芝,判斷協(xié)議頭
- 4、截取出方法名和參數(shù)
沒有參數(shù)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// URL:YYHttp://方法名
NSString *url = request.URL.absoluteString;
// 自定義協(xié)議頭
NSString *scheme = @"YYHttp://";
if ([url hasPrefix:scheme]) {
NSString *methodName = [url substringFromIndex:scheme.length];
[self performSelector:NSSelectorFromString(methodName) withObject:nil];
return NO;
}
return YES;
}
一個或者兩個參數(shù)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// url == YYHttp://sendMessage_number2_?200&300
NSString *url = request.URL.absoluteString;
NSString *scheme = @"YYHttp://";
if ([url hasPrefix:scheme]) {
// 獲得協(xié)議后面的路徑 path == sendMessage_number2_?200&300
NSString *path = [url substringFromIndex:scheme.length];
// 利用?切割路徑
NSArray *subpaths = [path componentsSeparatedByString:@"?"];
// 方法名 methodName == sendMessage:number2:
NSString *methodName = [[subpaths firstObject] stringByReplacingOccurrencesOfString:@"_" withString:@":"];
// 參數(shù) 200&300
NSString *param = [subpaths lastObject];
NSArray *subparams = nil;
if (subpaths.count == 2 || [param containsString:@"&"]) {
subparams = [param componentsSeparatedByString:@"&"];
}
// 取出前面的2個參數(shù)
NSString *firstParam = [subparams firstObject];
NSString *secondParam = subparams.count <= 1 ? nil : [subparams lastObject];
[self performSelector:NSSelectorFromString(methodName) withObject:firstParam withObject:secondParam];
return NO;
}
return YES;
}
三個或以上參數(shù)
- 這個時候就需要自定義方法去實現(xiàn)傳遞多個參數(shù)
- 需要用到
NSInvocation
- 只要下面這個方法定義好褥琐,那么直接傳入數(shù)組即可
一個或者兩個參數(shù)也可以使用下面這種方式
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects
{
// 方法簽名(方法的描述)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
if (signature == nil) {
// 一般在這里面拋出異常
//@throw [NSException exceptionWithName:@"方法名錯誤" reason:@"方法找不到" userInfo:nil];
//[NSException raise:@"方法名錯誤" format:@"%@方法找不到", NSStringFromSelector(selector)];
}
// NSInvocation : 利用一個NSInvocation對象包裝一次方法調用(方法調用者模狭、方法名、方法參數(shù)踩衩、方法返回值)
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
// 設置參數(shù)
NSInteger paramsCount = signature.numberOfArguments - 2; // 除self嚼鹉、_cmd以外的參數(shù)個數(shù)
paramsCount = MIN(paramsCount, objects.count);
for (NSInteger i = 0; i < paramsCount; i++) {
id object = objects[i];
if ([object isKindOfClass:[NSNull class]]) continue;
[invocation setArgument:&object atIndex:i + 2];
}
// 調用方法
[invocation invoke];
// 獲取返回值
id returnValue = nil;
if (signature.methodReturnLength) { // 有返回值類型贩汉,才去獲得返回值
[invocation getReturnValue:&returnValue];
}
return returnValue;
}