今天,记录一下iOS原生和React-Native之间的交互.如果第一次接触最好先移步至 http://www.cnblogs.com/shaoting/p/6388502.html 先看一下怎么在iOS原生中集成react-native模块.
iOS原生和React-Native之间的交互主要通过NativeModules实现.
先看RN->iOS原生
开发环境版本:
准备:
终端新建一个react-native项目或者使用上一篇文章建立的demo.
a.先使用Xcode打开,新建一个CalendarManager类,集成自NSObject即可.先在CalendarManager.h中导入相关类和实现协议RCTBridgeModule
1 // 2 // CalendarManager.h 3 // rnAndN 4 // 5 // Created by Shaoting Zhou on 2017/2/10. 6 // Copyright © 2017年 Facebook. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import <React/RCTBridgeModule.h> 11 #import <React/RCTLog.h> 12 @interface CalendarManager : NSObject<RCTBridgeModule> 13 14 @end
b.CalendarManager.m配置,为了实现该协议,需要含有一个宏:RCT_EXPORT_MODULE(),
1 // 2 // CalendarManager.m 3 // rnAndN 4 // 5 // Created by Shaoting Zhou on 2017/2/10. 6 // Copyright © 2017年 Facebook. All rights reserved. 7 // 8 9 #import "CalendarManager.h" 10 11 @implementation CalendarManager 12 13 RCT_EXPORT_MODULE();
c.react-native 通过NativeModules来实现传输和接受消息:
1 import { 2 AppRegistry, 3 StyleSheet, 4 Text, 5 View, 6 NativeModules 7 } from 'react-native'; 8 var CalendarManager = NativeModules.CalendarManager;
1.基本调用:
CalendarManager.m
// 接收传过来的 NSString RCT_EXPORT_METHOD(addEventOne:(NSString *)name){ NSLog(@"接收传过来的NSString+NSString: %@", name); }
RN:
CalendarManager.addEventOne('周少停');
2.字符串+字典:
CalendarManager.m
1 // 接收传过来的 NSString + NSDictionary 2 RCT_EXPORT_METHOD(addEventTwo:(NSString *)name details:(NSDictionary *)details) 3 { 4 RCTLogInfo(@"接收传过来的NSString+NSDictionary: %@ %@", name, details); 5 }
RN:
1 CalendarManager.addEventTwo('周少停',{job:'programmer'});
3.字符串+日期:
CalendarManager.m
1 // 接收传过来的 NSString + date日期 2 RCT_EXPORT_METHOD(addEventThree:(NSString *)name date:(NSDate *)date) 3 { 4 NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ; 5 [formatter setDateFormat:@"yyyy-MM-dd"]; 6 RCTLogInfo(@"接收传过来的NSString+NSDictionary: %@ %@", name, [formatter stringFromDate:date]); 7 }
RN:
CalendarManager.addEventThree('周少停',19910730);
4.点击调原生+回调
CalendarManager.m
1 // 对外提供调用方法,演示Callback 2 RCT_EXPORT_METHOD(testCallbackEventOne:(NSString *)name callback:(RCTResponseSenderBlock)callback) 3 { 4 NSLog(@"%@",name); 5 NSArray *events=@[@"1", @"2", @"3",@"4"]; //准备回调回去的数据 6 callback(@[[NSNull null],events]); 7 }
RN:
1 // 传原生一个字符串 + 回调 2 callBackOne = ()=>{ 3 CalendarManager.testCallbackEventOne(('我是RN给原生的'),(error, events) => { 4 if (error) { 5 console.error(error); 6 } else { 7 alert(events) 8 } 9 }) 10 }
5.Promises
CalendarManager.m
//Promises // 对外提供调用方法,演示Promise使用 RCT_REMAP_METHOD(testCallbackEventTwo, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSArray *events =@[@"one ",@"two ",@"three"];//准备回调回去的数据 if (events) { resolve(events); } else { NSError *error=[NSError errorWithDomain:@"我是Promise回调错误信息..." code:101 userInfo:nil]; reject(@"no_events", @"There were no events", error); } }
RN:
try{ var events=await CalendarManager.testCallbackEventTwo(); alert(events) }catch(e){ console.error(e); }
5.使用原生定义的常量
CalendarManager.m
1 - (NSDictionary *)constantsToExport 2 { 3 return @{ @"ValueOne": @"我是从原生定义的~" }; 4 }
RN:
alert(CalendarManager.ValueOne)
完整代码:
CalendarManager.m
1 // 2 // CalendarManager.m 3 // rnAndN 4 // 5 // Created by Shaoting Zhou on 2017/2/10. 6 // Copyright © 2017年 Facebook. All rights reserved. 7 // 8 9 #import "CalendarManager.h" 10 11 @implementation CalendarManager 12 13 RCT_EXPORT_MODULE(); 14 15 // 接收传过来的 NSString 16 RCT_EXPORT_METHOD(addEventOne:(NSString *)name){ 17 NSLog(@"接收传过来的NSString+NSString: %@", name); 18 } 19 // 接收传过来的 NSString + NSDictionary 20 RCT_EXPORT_METHOD(addEventTwo:(NSString *)name details:(NSDictionary *)details) 21 { 22 RCTLogInfo(@"接收传过来的NSString+NSDictionary: %@ %@", name, details); 23 } 24 25 // 接收传过来的 NSString + date日期 26 RCT_EXPORT_METHOD(addEventThree:(NSString *)name date:(NSDate *)date) 27 { 28 NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ; 29 [formatter setDateFormat:@"yyyy-MM-dd"]; 30 RCTLogInfo(@"接收传过来的NSString+NSDictionary: %@ %@", name, [formatter stringFromDate:date]); 31 } 32 33 // 对外提供调用方法,演示Callback 34 RCT_EXPORT_METHOD(testCallbackEventOne:(NSString *)name callback:(RCTResponseSenderBlock)callback) 35 { 36 NSLog(@"%@",name); 37 NSArray *events=@[@"1", @"2", @"3",@"4"]; //准备回调回去的数据 38 callback(@[[NSNull null],events]); 39 } 40 41 //Promises 42 // 对外提供调用方法,演示Promise使用 43 RCT_REMAP_METHOD(testCallbackEventTwo, 44 resolver:(RCTPromiseResolveBlock)resolve 45 rejecter:(RCTPromiseRejectBlock)reject) 46 { 47 NSArray *events =@[@"one ",@"two ",@"three"];//准备回调回去的数据 48 if (events) { 49 resolve(events); 50 } else { 51 NSError *error=[NSError errorWithDomain:@"我是Promise回调错误信息..." code:101 userInfo:nil]; 52 reject(@"no_events", @"There were no events", error); 53 } 54 } 55 56 - (NSDictionary *)constantsToExport 57 { 58 return @{ @"ValueOne": @"我是从原生定义的~" }; 59 } 60 61 62 @end
RN:
1 /** 2 * Sample React Native App 3 * https://github.com/facebook/react-native 4 * @flow 5 */ 6 7 import React, { Component } from 'react'; 8 import { 9 AppRegistry, 10 StyleSheet, 11 Text, 12 View, 13 NativeModules 14 } from 'react-native'; 15 var CalendarManager = NativeModules.CalendarManager; 16 17 18 export default class NativeAddRN extends Component { 19 render() { 20 return ( 21 <View style={styles.container}> 22 <Text style={styles.welcome} onPress={()=>this.passValueToNativeOne()}>点击往原生传字符串</Text> 23 <Text style={styles.welcome} onPress={()=>this.passValueToNativeTwo()}>点击往原生传字符串+字典</Text> 24 <Text style={styles.welcome} onPress={()=>this.passValueToNativeThree()}>点击往原生传字符串+日期</Text> 25 <Text style={styles.welcome} onPress={()=>this.callBackOne()}>点击调原生+回调</Text> 26 <Text style={styles.welcome} onPress={()=>this.callBackTwo()}>Promises</Text> 27 <Text style={styles.welcome} onPress={()=>this.useNativeValue()}>使用原生定义的常量</Text> 28 </View> 29 ); 30 } 31 // 传原生一个字符串 32 passValueToNativeOne = ()=>{ 33 CalendarManager.addEventOne('周少停'); 34 } 35 // 传原生一个字符串 + 字典 36 passValueToNativeTwo = ()=>{ 37 CalendarManager.addEventTwo('周少停',{job:'programmer'}); 38 } 39 // 传原生一个字符串 + 日期 40 passValueToNativeThree = ()=>{ 41 CalendarManager.addEventThree('周少停',19910730); 42 } 43 // 传原生一个字符串 + 回调 44 callBackOne = ()=>{ 45 CalendarManager.testCallbackEventOne(('我是RN给原生的'),(error, events) => { 46 if (error) { 47 console.error(error); 48 } else { 49 alert(events) 50 } 51 }) 52 } 53 //Promise回调 54 async callBackTwo(){ 55 try{ 56 var events=await CalendarManager.testCallbackEventTwo(); 57 alert(events) 58 }catch(e){ 59 console.error(e); 60 } 61 } 62 //使用原生定义的常量 63 useNativeValue = ()=>{ 64 alert(CalendarManager.ValueOne) 65 } 66 67 } 68 69 const styles = StyleSheet.create({ 70 container: { 71 flex: 1, 72 marginTop:100 73 }, 74 welcome: { 75 fontSize: 20, 76 textAlign: 'center', 77 margin: 10, 78 }, 79 instructions: { 80 textAlign: 'center', 81 color: '#333333', 82 marginBottom: 5, 83 }, 84 }); 85 86 AppRegistry.registerComponent('NativeAddRN', () => NativeAddRN);
演示效果和demo源码:https://github.com/pheromone/IOS-native-and-React-native-interaction
另:因为react native并不提供清除缓存功能,所以只能通过react native调用原生来实现计算缓存大小和清除缓存功能:
iOS:
1 // 2 // CalendarManager.m 3 // rnAndN 4 // 5 // Created by Shaoting Zhou on 2017/2/10. 6 // Copyright © 2017年 Facebook. All rights reserved. 7 // 8 9 #import "CalendarManager.h" 10 @implementation CalendarManager 11 12 RCT_EXPORT_MODULE(); 13 14 // 清理缓存 15 RCT_EXPORT_METHOD(cleanCache:(RCTResponseSenderBlock)callback) 16 { 17 NSURLCache *httpCache = [NSURLCache sharedURLCache]; 18 [httpCache removeAllCachedResponses]; 19 NSUInteger cache = [httpCache currentDiskUsage]; 20 callback(@[[NSNull null],@(cache)]); 21 } 22 // 计算缓存 23 RCT_EXPORT_METHOD(cacheSize:(RCTResponseSenderBlock)callback) 24 { 25 NSURLCache *httpCache = [NSURLCache sharedURLCache]; 26 NSUInteger cache = [httpCache currentDiskUsage]; 27 callback(@[[NSNull null],@(cache)]); 28 } 29 @end
RN:
再进入清除缓存界面时,就计算缓存大小:
1 componentWillMount() { 2 CalendarManager.cacheSize((error, events) => { 3 if (error) { 4 console.error(error); 5 } else { 6 this.setState({ 7 cache:Math.round(events/1024) //缓存大小 8 }) 9 } 10 }) 11 }
清除缓存按钮响应时间:
1 clearRom =()=>{ 2 CalendarManager.cleanCache((error, events) => { 3 if (error) { 4 console.error(error); 5 } else { 6 this.setState({ 7 cache:0 //这里本应该是清除之后的数据Math.round(events/1024).应该是0才对,但是总是清不干净,我就直接置为0了 8 }) 9 } 10 }) 11 }
iOS清除缓存源码可以参考该微博项目中的:https://github.com/pheromone/react_native_weibo
安卓待写....