JS 和 OC 交互

2017-03-09  本文已影响45人  iOS104
  • 之前项目中OC和JS交互一直用的对UIWebview方法拦截方案,根据自定义的url来调用OC的方法.
  • 考虑到性能问题,现在切换WKWebView

下面主要讲述下从iOS6至今,Native与JavaScript的交互方法

iOS 6 UIWebview&&JavaScript

#pragma mark UIWebViewDelegate

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
   
   NSURL *url = [request URL];
   // hybrid://Smart:3/pushViewController?{}
   if ([url.scheme isEqualToString:@"hybrid"]) {
       [self handleRequest:url];
       return NO;
   }
   
   return YES;
}

- (void)handleRequest:(NSURL *)url {
   NSString *handlerName = [url.path substringFromIndex:1];
   
   NSString *queryString = [url.query stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
   NSInteger sid = [url.port integerValue];
   NSDictionary *parameters = [queryString tp_objectFromJSONString];
   
   SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@:parameters:", handlerName]);
   if (![self respondsToSelector:selector]) {
       return;
   }
   
   IMP imp = [self methodForSelector:selector];
   void (*func)(id, SEL,NSInteger, NSDictionary *) = (void *)imp;
   func(self, selector,sid, parameters);
}

- (void)pushViewController:(NSInteger)sid parameters:(NSDictionary *)parameters
{
   
}
[self.webView stringByEvaluatingJavaScriptFromString:@""];

iOS 7 UIWebview&&JavaScriptCore

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"js call oc";

    NSString *path = [[[NSBundle mainBundle] bundlePath]  stringByAppendingPathComponent:@"JSCallOC.html"];
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]];
    [self.webView loadRequest:request];
}

#pragma mark - UIWebViewDelegate

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    // 以 html title 设置 导航栏 title
    self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    // Undocumented access to UIWebView's JSContext
    self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 打印异常
    self.context.exceptionHandler =
    ^(JSContext *context, JSValue *exceptionValue)
    {
        context.exception = exceptionValue;
        NSLog(@"%@", exceptionValue);
    };
 
    
    // 以 block 形式关联 JavaScript function
    self.context[@"alert"] =
    ^(NSString *str)
    {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"msg from js" message:str delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
        [alert show];
    };
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"oc call js";
    self.context = [[JSContext alloc] init];
    [self.context evaluateScript:[self loadJsFile:@"test"]];
}

- (NSString *)loadJsFile:(NSString*)fileName
{
    NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"js"];
    NSString *jsScript = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    return jsScript;
}

- (IBAction)sendToJS:(id)sender {
    NSNumber *inputNumber = [NSNumber numberWithInteger:[self.textField.text integerValue]];
    JSValue *function = [self.context objectForKeyedSubscript:@"factorial"];
    JSValue *result = [function callWithArguments:@[inputNumber]];
    self.showLable.text = [NSString stringWithFormat:@"%@", [result toNumber]];
}

iOS 8 WKWebView && JavaScript

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"Native"]) {
        NSLog(@"message.body:%@", message.body);
        //如果是自己定义的协议, 再截取协议中的方法和参数, 判断无误后在这里手动调用oc方法
        NSMutableDictionary *param = [self queryStringToDictionary:message.body];
        NSLog(@"get param:%@",[param description]);
        
        NSString *func = [param objectForKey:@"func"];
        
        //调用本地函数
        if([func isEqualToString:@"alert"])
        {
            [self showMessage:@"来自网页的提示" message:[param objectForKey:@"message"]];
        }
     
    }
}

- (NSMutableDictionary*)queryStringToDictionary:(NSString*)string {
    NSMutableArray *elements = (NSMutableArray*)[string componentsSeparatedByString:@"&"];
    NSMutableDictionary *retval = [NSMutableDictionary dictionaryWithCapacity:[elements count]];
    for(NSString *e in elements) {
        NSArray *pair = [e componentsSeparatedByString:@"="];
        [retval setObject:[pair objectAtIndex:1] forKey:[pair objectAtIndex:0]];
    }
    return retval;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"JS调用WKWebView";
    
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.userContentController = [[WKUserContentController alloc] init];
    [config.userContentController addScriptMessageHandler:self name:@"Native"];
    
    self.myWebView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
    self.myWebView.UIDelegate = self;
    [self.view addSubview:self.myWebView];
    
    [self loadHtml:@"JSWKWebView"];
}
上一篇下一篇

猜你喜欢

热点阅读