iOS js和OC方法交互

前段时间公司做的app内嵌了h5页面,其中有js与iOS原生方法交互的问题,我研究了一段时间,闲来无事,写了一个demo,以供遇到难题的小伙伴参考。

github地址 https://github.com/jie0394/HybridAppTest

废话不多说,开始贴代码,webView页面,

//
//  ViewController.m
//  HybridAppTest
//
//  Created by 李然豪 on 2017/4/24.
//  Copyright © 2017年 李然豪. All rights reserved.
//

#import "ViewController.h"
#import "SZKoclaJScontextModel.h"//这个model里面已经引用了<JavaScriptCore/JavaScriptCore.h>,所以此页面不用再重复引用
@interface ViewController ()<UIWebViewDelegate,SZKoclaJScontextModelDelegate>
@property (strong, nonatomic)UIWebView *webView;
@property (nonatomic, strong) JSContext *jsContext;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
    
    [self.view addSubview:_webView];
    
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.webView.backgroundColor = [UIColor whiteColor];
    
    self.webView.delegate = self;
    NSURL *htmlURL = [[NSBundle mainBundle] URLForResource:@"index.html" withExtension:nil];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:htmlURL];
    
    self.webView.backgroundColor = [UIColor clearColor];
    
    [self.webView loadRequest:request];
    [self.view addSubview:self.webView];
    
    UIBarButtonItem *rightItem  = [[UIBarButtonItem alloc] initWithTitle:@"调用js" style:UIBarButtonItemStylePlain target:self action:@selector(btnJS:)];
    
    [self.navigationItem setRightBarButtonItem:rightItem];
    // Do any additional setup after loading the view, typically from a nib.
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
    self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
/*****************说明**************
 用model的原因是防止内存泄漏
 
 很多demo是这样写的
 self.jsContext[@"web"] = self;
 但是这样写会造成循环引用,导致内存泄漏
 ****************/
    SZKoclaJScontextModel *model = [SZKoclaJScontextModel new];
    self.jsContext[@"web"] = model;//js方法有别名的,将别名写到这,使用代理方法进行回调,
    model.jsContext = self.jsContext;
    
    [model setDelegate:self];
    
    [self callCamera:self.jsContext];//js方法没有别名,使用block回调;
    
    self.jsContext.exceptionHandler =
    ^(JSContext *context, JSValue *exceptionValue)
    {
        context.exception = exceptionValue;
        NSLog(@"%@", exceptionValue);
    };

}


#pragma mark js调用iOS方法
-(void)share{
    NSArray *args = [JSContext currentArguments];
    [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"shareCallback()"]];//方法回调成功弹出js的alert;
    NSLog(@"%@",args);
//
//  SZKoclaJScontextModel.h
//  JS_OC_JavaScriptCore
//
//  Created by 李然豪 on 17/4/7.
//  Copyright © 2017年 李然豪. All rights reserved.
//

#import <Foundation/Foundation.h>

#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSExportDelegate <JSExport>

//-(void)scanClick;
//
//-(void)payClick;
-(void)share;
@end
@protocol SZKoclaJScontextModelDelegate <NSObject>

//-(void)scanClick;
//
//-(void)payClick;

-(void)share;
@end
@interface SZKoclaJScontextModel : NSObject<JSExportDelegate>
@property (strong, nonatomic)JSContext *jsContext;

@property (weak, nonatomic)id<SZKoclaJScontextModelDelegate>delegate;
@end

}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}#pragma mark iOS调用js方法-(void)btnJS:(id)sender{ [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"callCamera()"]];//弹出js的alert; NSString *result = [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"callBack(%@,%@)",@"123",@"456"]]; NSLog(@"%@",result); }-(void)callCamera:(JSContext *)context{ context[@"callCamera"]=^() {// NSArray *args = [JSContext currentArguments];//如果有参数,使用这种方法获取参数; NSLog(@"callCamera"); };}@end
 接下来就是model的页面了 
 

.h页面

//
//  SZKoclaJScontextModel.h
//  JS_OC_JavaScriptCore
//
//  Created by 李然豪 on 17/4/7.
//  Copyright © 2017年 李然豪. All rights reserved.
//

#import <Foundation/Foundation.h>

#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSExportDelegate <JSExport>

//-(void)scanClick;
//
//-(void)payClick;
-(void)share;
@end
@protocol SZKoclaJScontextModelDelegate <NSObject>

//-(void)scanClick;
//
//-(void)payClick;

-(void)share;
@end
@interface SZKoclaJScontextModel : NSObject<JSExportDelegate>
@property (strong, nonatomic)JSContext *jsContext;

@property (weak, nonatomic)id<SZKoclaJScontextModelDelegate>delegate;
@end

.m文件


//
//  SZKoclaJScontextModel.m
//  JS_OC_JavaScriptCore
//
//  Created by 李然豪 on 17/4/7.
//  Copyright © 2017年 李然豪. All rights reserved.
//

#import "SZKoclaJScontextModel.h"

@implementation SZKoclaJScontextModel
//-(void)scanClick{
//    if ([self.delegate respondsToSelector:@selector(scanClick)]) {
//        [self.delegate scanClick];
//    }
//}
//
//-(void)payClick{
//    if ([self.delegate respondsToSelector:@selector(payClick)]) {
//        [self.delegate payClick];
//    }
//}
-(void)share{
    if ([self.delegate respondsToSelector:@selector(share)]) {
        [self.delegate share];
    }
}
@end

index.html页面


<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div style="margin-top: 100px">
            <h1>Objective-C和JavaScript交互的那些事</h1>
            <input type="button" value="CallCamera" onclick="callCamera()">
        </div>
        <div>
            <input type="button" value="Share" onclick="callShare()">
        </div>
        
        <script>
            var callShare = function() {
                
                  web.share("123","123");
            }
        
        
        var shareCallback = function(){
            alert('share回调success');
        }
        
        
        function callCamera(){
            alert('callCamera调用success');
        }
        
        function callBack(s1,s2){
            return s1+s2;
        }
        </script>
    </body>
</html>

混合并不是太复杂,理解了原理就比较好用了


猜你喜欢

转载自blog.csdn.net/jie0394/article/details/70598453