OC与JS交互 初体会

第一篇博客,有点小紧张、小期待,会不会有人看?有也好,没有也罢,权当自己图个乐儿,记录近来学到的知识。闲话少说,进入正题!

OC与JS交互的方式:1、使用UIWebView通过拦截Request完成JS调取OC,通过stringByEvaluatingJavaScriptFromString注入JS函数或者取数据完成OC调取JS

2、使用WKWebView通过- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler完成OC调取JS,通过- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name拦截完成JS调取OC,还可以通过- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name完成JS调用OC

3、苹果有提供JavaScriptCore库,可以完成交互

4、第三方库WebViewJavascriptBridge

 

一、使用UIWebView

拦截Request完成JS调取OC

 1 #pragma mark - UIWebViewDelegate
 2 
 3 /**
 4  这些都是JS响应的样式
 5  UIWebViewNavigationTypeLinkClicked,        点击
 6  UIWebViewNavigationTypeFormSubmitted,      提交
 7  UIWebViewNavigationTypeBackForward,        返回
 8  UIWebViewNavigationTypeReload,             刷新
 9  UIWebViewNavigationTypeFormResubmitted,    重复提交
10  UIWebViewNavigationTypeOther               其他
11 
12  */
13 // 加载所有请求数据,以及控制是否加载
14 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
15     
16     NSLog(@"%@",request.URL.scheme); // 标识 我们自己协议
17     NSLog(@"%@",request.URL.host);   // 方法名
18     NSLog(@"%@",request.URL.pathComponents);  // 参数
19 
20     // JS 调用OC 的原理就是 拦截URL
21     NSString *scheme = request.URL.scheme;
22     if ([scheme isEqualToString:@"custom"]) {
23         NSLog(@"来了,我们自定义的协议");
24         
25         NSArray *args = request.URL.pathComponents;
26         NSString *methodName = args[1];
27         
28 
29         SEL methodSel = NSSelectorFromString(methodName);
30         if ([self respondsToSelector:methodSel]) {
31 
32             [self performSelector:methodSel withObject:args[2]];
33 
34         }
35     
36         return NO;
37     }
38     
39     return YES;
40 }

通过stringByEvaluatingJavaScriptFromString注入JS函数或者取数据完成OC调取JS

// 加载完成
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    //获取title
    NSString *titlt = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    self.title = titlt;
    
}

//调用JS函数
NSString *result = [self.webView stringByEvaluatingJavaScriptFromString:@"showAlert('HELLO')"];

 

二、使用WKWebView

拦截Request

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSURL *URL = navigationAction.request.URL;
    NSString *scheme = [URL scheme];
    if ([scheme isEqualToString:@"tzedu"]) {
        
        NSString *host = [URL host];
        if ([host isEqualToString:@"jsCallOC"]) {
            NSMutableDictionary *temDict = [self decoderUrl:URL];
            NSString *username = [temDict objectForKey:@"username"];
            NSString *password = [temDict objectForKey:@"password"];
            NSLog(@"%@---%@",username,password);
            
        }else{
            NSLog(@"不明地址 %@",host);
        }

        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    self.title = webView.title;
}

MessageHandler:

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"messgaeOC"];
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    //注意循环引用
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"messgaeOC"];
}
#pragma mark - WKScriptMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    NSLog(@"message == %@ --- %@",message.name,message.body);
    
}

OC调取JS:

 NSString *jsStr2 = @"showAlert('messageHandle:OC-->JS')";
    [self.webView evaluateJavaScript:jsStr2 completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"%@----%@",result, error);
    }];

三、JavaScriptCore

 

 JSContext:给JavaScript提供运行的上下文环境
 JSValue:JavaScript和Objective-C数据和方法的桥梁
 JSManagedValue:管理数据和方法的类
 JSVirtualMachine:处理线程相关,使用较少
 JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    
    NSString *titlt = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    self.title = titlt;
    
    //JSContext就为其提供着运行环境 H5上下文
    JSContext *jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    self.jsContext = jsContext;
    __weak typeof(self) weakSelf = self;

    // 异常处理
    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        context.exception = exception;
        NSLog(@"exception == %@",exception);
        NSLog(@"%@",context);
    };
    
    // 提供给JS全局变量
    [self.jsContext evaluateScript:@"var arr = [3, 'Hello', 'abc'];"];
    
    self.jsContext[@"showMessage"] = ^() {
        
        JSValue *thisValue = [JSContext currentThis];
        NSLog(@"thisValue = %@",thisValue);
        JSValue *cValue = [JSContext currentCallee];
        NSLog(@"cValue = %@",cValue);
        NSArray *args = [JSContext currentArguments];
        NSLog(@"来了:%@",args);
        
        NSDictionary *dict = @{@"name":@"cooci",@"age":@18};
        
        [[JSContext currentContext][@"ocCalljs"] callWithArguments:@[dict]];
    };
    
    // 因为是全局变量 可以直接获取
    JSValue *arrValue = self.jsContext[@"arr"];
    NSLog(@"arrValue == %@",arrValue);
    
    //纠正用法
//    JSValue *value = [JSValue valueWithObject:@"test“ inContext:context];
//    JSManagedValue *managedValue = [JSManagedValue managedValueWithValue:value andOwner:self];

    
    self.jsContext[@"showDict"] = ^(JSValue *value) {
        //注意线程问题
        NSArray *args = [JSContext currentArguments];
        JSValue *dictValue = args[0];
        NSDictionary *dict = dictValue.toDictionary;
        NSLog(@"%@",dict);
        
        // 模拟用
        int num = [[arrValue.toArray objectAtIndex:0] intValue];
        num += 10;
        NSLog(@"arrValue == %@   num == %d",arrValue.toArray,num);
        dispatch_async(dispatch_get_main_queue(), ^{
            weakSelf.showLabel.text = dict[@"name"];
        });
    };
    
    
    //异常收集
    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        weakSelf.jsContext.exception = exception;
        NSLog(@"exception == %@",exception);
    };
    
    
    // JS 操作对象
    KC_JSObject *kcObject = [[KC_JSObject alloc] init];
    self.jsContext[@"kcObject"] = kcObject;
    

    // 打开相册
    self.jsContext[@"getImage"] = ^() {
        
        weakSelf.imagePicker = [[UIImagePickerController alloc] init];
        weakSelf.imagePicker.delegate = weakSelf;
        weakSelf.imagePicker.allowsEditing = YES;
        weakSelf.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [weakSelf presentViewController:weakSelf.imagePicker animated:YES completion:nil];
    };
    
}


#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>

@protocol KCProtocol <JSExport>

- (void)letShowImage;
JSExportAs(getSum, -(int)getSum:(int)num1 num2:(int)num2);

@end

@interface KC_JSObject : NSObject<KCProtocol>
@end



#import "KC_JSObject.h"

@implementation KC_JSObject

- (void)letShowImage{
    
    NSLog(@"打开相册,上传图片");
}

- (int)getSum:(int)num1 num2:(int)num2{
    return num1+num2;
}

@end

四、WebViewJavascriptBridge

https://github.com/marcuswestin/WebViewJavascriptBridge

转载于:https://www.cnblogs.com/madeByGx/p/9896706.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值