在UIWebview里面一般有两种方法与JS交互,一种是JSContext,另外一种就是拦截协议。而使用JSContext与JS交互的同学,一般都对webViewDidFinishLoad这个代理比较熟悉,因为一般来说和网上的的多数资料都会让你在这个代理里面注入JSContext对象。但是这时候就会导致一个问题,需要全部加载JS的东西后才能与JS进行交互,有时候前端会提出需要在加载的中途进行交互。
其实UIWebview里面还有一个webViewDidStartLoad代理方法,如果你在这个方法里面也注入JSContext对象,在某种程度上可以解决这个问题,但是在打开webview里面的二级界面的时候可能会出现问题,因为可能在与JS交互的时候,JSContext提前销毁了,因为他是在webViewDidStartLoad中注入的。如果你在- (void)viewDidLoad中注入,应该也会有同一个问题。
这个时候可以使用webkit的didCreateJavaScriptContext这个API,这样可以比较完美的解决上面提出的问题。或者也可以使用UIWebView-TS_JavaScriptContext这个开源库,当然这个开源库其实也是使用了这个API,didCreateJavaScriptContext的具体代码如下
#import 《Foundation/Foundation.h》
#import 《JavaScriptCore/JavaScriptCore.h》
@interface NSObject_JSContextTracker : NSObject
@end
#import "NSObject+JSContextTracker.h"
@implementation NSObject (JSContextTracker)
- (void)webView:(id)unused didCreateJavaScriptContext:(JSContext *)ctx forFrame:(id)alsoUnused {
if (!ctx)
return;
[[NSNotificationCenter defaultCenter] postNotificationName:@"LLCreatJSContex" object:ctx];
}
@end
最后就是在你需要调用的webview界面viewDidLoad里面注册通知就OK
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(creatJSContex:) name:@"LLCreatJSContex" object:nil];
-(void)creatJSContex:(NSNotification*)noti
{
// NSLog(@"%@",noti);
//注意以下代码如果不在主线程调用会发生闪退。
dispatch_async( dispatch_get_main_queue(), ^{
self.jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"czb"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
});
}
网友评论