react-native: ios原生调用js方法

JavaScript07

react-native: ios原生调用js方法,第1张

ReactEventEmit.h

#import <React/RCTEventEmitter.h>

#import <React/RCTBridgeModule.h>

@interface ReactEventEmit : RCTEventEmitter<RCTBridgeModule>

-(void)goToCashier:(NSString*) result

@end

ReactEventEmit.m

#import "ReactEventEmit.h"

@implementation ReactEventEmit

@synthesize bridge = _bridge

RCT_EXPORT_MODULE(ReactEventEmit)

+ (id)allocWithZone:(NSZone*)zone {

    staticReactEventEmit*sharedInstance =nil

    staticdispatch_once_tonceToken

    dispatch_once(&onceToken, ^{

        sharedInstance = [superallocWithZone:zone]

    })

    returnsharedInstance

}

-(NSArray *)supportedEvents{

    return @[@"goToCashier"]

}

-(void)goToCashier:(NSString*) result

{

    NSLog(@"======== cashierSuccess ========== %@",result)

    [self sendEventWithName:@"goToCashier" body:@{@"result": result}]

}

@end

RN的module初始化是由RN内部实现的,所以我们调用这个实例的时候,必须是这样子:

ReactEventEmit *emit = [ReactEventEmit allocWithZone:nil]

 [emit goToCashier:@"fail"]

JS端调用:

const ReactEventEmit = NativeModules.ReactEventEmit

const myReactEventEmit = new NativeEventEmitter(ReactEventEmit)

this.listener = myReactEventEmit.addListener('goToCashier', (data: { result: string }) =>{

        console.warn('====== cashierSuccess ======= ' + JSON.stringify(data))

        this.process(data.result)

      })

基本流程:

先看一下Web中,我们给h1标签添加一个onclick事件,让它在被点击之后,修改当前的url。

Web中的HTML代码:

<html>

<head>

<script>

function getInfo(name)

{

window.location = "/getInfo/"+name

}

</script>

</head>

<body>

<h1 onclick="getInfo('why')">Name</h1>

</body>

</html>

iOS中,先拖拽WebView,访问localhost,然后通过WebView的委托事件监听url跳转操作,并且把跳转截取下来。

也就是说,在onclick的时候,普通浏览器灰跳转到那个url,但是在iOS的这个WebView里面,这个跳转会被拦截,

用这种方式可以巧妙地实现JS调用iOS的原生代码:

//

// DWViewController.m

// DareWayApp

//

// Created by why on 14-6-3.

// Copyright (c) 2014年 DareWay. All rights reserved.

//

#import "DWViewController.h"

@interface DWViewController ()

@property (weak, nonatomic) IBOutlet UIWebView *myWebview // 主页面

@end

@implementation DWViewController

- (void)viewDidLoad

{

[super viewDidLoad]

// Do any additional setup after loading the view, typically from a nib.

// 适配iOS6的状态栏

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {

_myWebview.frame = CGRectMake(0,20,self.view.frame.size.width,self.view.frame.size.height-20)

}

// 加载制定的URL

NSURL *url =[NSURL URLWithString:@"http://localhost"]

NSURLRequest *request =[NSURLRequest requestWithURL:url]

[_myWebview setDelegate:self]

[_myWebview loadRequest:request]

}

// 网页中的每一个请求都会被触发

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

{

// 每次跳转时候判断URL

if([request.mainDocumentURL.relativePath isEqualToString:@"/getInfo/why"])

{

NSLog(@"why")

return NO

}

return YES

}

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning]

// Dispose of any resources that can be recreated.

}

@end

目前iOS项目中 Webview 几乎都会用到,iOS 8 之前使用UIWebView,iOS 8 之后 Apple 就不推荐使用了,目前已经放弃了,如果项目中存在就无法上架了,需要转为WKWebView了,说实话 UIWebView 是有性能上的缺陷,内存优化不够友好等,但是不得不说这是老的iOS开发人员用的最熟练熟悉的了,用起来得心应手。非迫不得已还真不愿转到WKWebView。好吧,既然已经这样了,又何必苦苦单恋一支花呢?

看了网上教程很多,自己使用小结一下,简单易用,本文适用于菜鸟级开发,废话不说了,

最主要的方法:发送消息

注意:对象名和方法名jumpUserProtocol名字的一致,参数可以是常用的NSArray,NSDictionary等类型,先说下在这个Demo中其实没用上,用的方法名判断的。

注意: addScriptMessageHandler

name为方法名 ,和JS 中的保持一致,添加脚本,相当于给Webview添加一个监听,有这个功能来处理JS。

在WKScriptMessageHandler代理方法中处理回调,实现自己的逻辑。

上面就是JS调用OC原生实现。

这个其实很简单,就一个方法: