您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關React Native與IOS端之間交互的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
首先最好了解一點關于 oc 的語法知識
1.創建聲明文件nativeModule.h
#import <Foundation/Foundation.h> #import <React/RCTBridgeModule.h> @interface nativeModule : NSObject <RCTBridgeModule> @end
2.創建文件nativeModule.m
#import <Foundation/Foundation.h> #import "nativeModule.h" @interface nativeModule () @end @implementation nativeModule @end
這是添加完文件后的結構目錄
關于 interface 的區別:
.h里面的@interface,它是供其它Class調用的。它的@property和functions,都能夠被其它Class“看到”(public)
而.m里面的@interface,在OC里叫作Class Extension,是.h文件中@interface的補充。但是.m文件里的@interface,對外是不開放的,只在.m文件里可見(private)
因此,我們將對外開放的方法、變量放到.h文件中,而將不想要對外開放的變量放到.m文件中(.m文件的方法可以不聲明,直接用)。
在 .m 文件中添加方法:
// 省略上面的代碼 @implementation nativeModule // 這句代碼是必須的 用來導出 module, 這樣才能在 RN 中訪問 nativeModule這個 module RCT_EXPORT_MODULE(); // 接收字符串 RCT_EXPORT_METHOD(addHelloWord:(NSString *)name location:(NSString *)location) { NSLog(@"%@,%@", name, location); } @end
RN 代碼:
import { Button, NativeModules } from 'react-native' const { nativeModule } = NativeModules <Button title={'傳 2 個參數給 native'} onPress={() => { nativeModule.addHelloWord('你的名字', '位置:浙江') }}/>
點擊此按鈕的作用,就是將 '你的名字', '位置:浙江' 這 2 個字符串傳遞到了原生端
在 .m 文件中添加:
// 只接受一個參數——傳遞給 JavaScript 回調函數的參數數組。 RCT_EXPORT_METHOD(checkIsRoot:(RCTResponseSenderBlock)callback) { NSArray *array = @[@"string", @"number"]; callback(array); }
在 RN 中添加代碼:
<Button title={'js 傳一個回調給 native,回調中收到一個數組'} onPress={() => { nativeModule.checkIsRoot((str: string, num: string) => { console.log(str, num) }) }}/>
這是在 RN 中 給原生端傳遞了一個回調函數,用來解決,部分操作完成后的回調, ** 如果 callback 多次調用 RN 會報錯 **
在 .m 文件中添加代碼:
@interface nativeModule () @property (nonatomic) RCTPromiseResolveBlock normalResolve; @property (nonatomic) RCTPromiseRejectBlock normalReject; @property (nonatomic) NSInteger num; @end // 這是一個計時器 -(void)startTime: (NSArray*) data{ NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { NSArray *events =@[@"Promise ",@"test ",@" array"]; if (events) { self.normalResolve(events); [timer invalidate]; } else { [timer invalidate]; NSError *error=[NSError errorWithDomain:@"我是回調錯誤信息..." code:101 userInfo:nil]; self.normalReject(@"no_events", @"There were no events", error); } }]; [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } // 回調給RN的參數,回調的錯誤信息 RCT_EXPORT_METHOD(getHBDeviceUniqueID: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { // 要執行的任務 self.normalResolve = resolve; self.normalReject = reject; [self performSelectorOnMainThread:@selector(startTime:) withObject: [NSArray arrayWithObjects: @"1", @"2", nil] waitUntilDone:YES]; }
在 RN 中添加代碼:
<Button title={'native傳一個 promise 給 JS'} onPress={() => { nativeModule.getHBDeviceUniqueID().then((arr: string[]) => { console.log('resolve', arr) }).catch((err: string) => { console.error(err) }) }}/>
nativeModule.getHBDeviceUniqueID 的執行他是一個 promise,可以獲取原生端的回調, 其實和方法 2 差不多
在 .m 文件中添加:
// 這是一個計時器2 -(void)startTime2: (NSArray*) data{ NSLog(@"data%@",data); NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { NSLog(@"%d", (int)self.num); self.num = self.num + 1; NSLog(@"%d", (int)self.num); if (self.num > 4) { [timer invalidate]; NSLog(@"end"); self.normalResolve(data); } }]; [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } // RCT_REMAP_METHOD 與RCT_EXPORT_METHOD相同,但是該方法是在JS線程上從JS同步調用的,可能會返回結果。 // 同步可能會有性能問題 建議除了 promise 以外都別使用 RCT_REMAP_METHOD(findEvents, findEventsWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { self.normalResolve = resolve; self.normalReject = reject; self.num = 0; [self performSelectorOnMainThread:@selector(startTime2:) withObject: [NSArray arrayWithObjects: @"1", @"2", nil] waitUntilDone:YES]; }
在 RN 端添加代碼:
<Button title={'native傳一個 promise 給 JS2'} onPress={() => { nativeModule.findEvents().then((arr: string[]) => { console.log('resolve', arr) }).catch((err: string) => { console.error(err) }) }}/>
方法 4 和方法 3 大體一致,但是有一點不同,就是 RCT_REMAP_METHOD 使用此方法會將代碼變成同步狀態
在 appDelegate.m 文件中添加代碼:
NSArray *imageList = @[@"http://foo.com/bar1.png", @"http://foo.com/bar2.png"]; NSDictionary *props = @{@"images" : imageList}; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"learn" initialProperties:props]; // 這一行代碼原本就有,不同點在于 initialProperties:props
在 RN 端寫入:
// 重寫 APP , images就是 iOS 提供的數據,這里我們通過 context 來傳遞數據 export default class App extends React.Component<{ images: string[] }> { render() { return <NativeProps.Provider value={this.props.images}> <AppContainer/> </NativeProps.Provider> } } // 在 hooks 里簡單的使用 const images = useContext(NativeProps); <Text>這是從 native 端傳來的初始數據{JSON.stringify(images)}</Text>
在 .m 文件中添加代碼:
// 可供監聽的事件名稱 - (NSArray<NSString *> *)supportedEvents { return @[@"EventReminder"]; } RCT_EXPORT_METHOD(postNotificationEvent:(NSString *)name) { NSLog(@"calendarEventReminderReceived"); [self sendEventWithName:@"EventReminder" body:@{@"name": name}];; } - (void)calendarEventReminderReceived:(NSNotification *)notification { // 這是官網的例子 NSLog(@"calendarEventReminderReceived"); NSString *eventName = notification.userInfo[@"name"]; [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}]; } RCT_EXPORT_METHOD(Send){ NSDictionary *dict = @{@"name" : @"veuimyzi"}; NSNotification *notification = [[NSNotification alloc] initWithName:@"EventReminder" object:nil userInfo:dict] ; [self calendarEventReminderReceived:notification]; }
在 RN 中添加代碼:
const ManagerEmitter = new NativeEventEmitter(nativeModule) const [msg, setMsg] = useState([]) // hooks 中的使用,類似于 componentDidMount 生命周期 useEffect(() => { const subscription = ManagerEmitter.addListener( 'EventReminder', (reminder) => { setMsg(prevState => { return prevState.concat(reminder.name) }) console.log('這是監聽的EventReminder事件回復', reminder.name) } ) return () => { subscription.remove() } }, []) <Button title={'js 監聽事件,讓 native 給 js 發通知'} onPress={() => { nativeModule.postNotificationEvent('test') }}/> <Button title={'js 監聽事件,讓 native 給 js 發通知 send'} onPress={() => { nativeModule.Send() }}/> { msg.map((item, index) => { return <Text key={item + index}>item:{item}</Text> }) }
關于 postNotificationEvent 方法是屬于最簡單的使用, 在原生端調用 sendEventWithName 就可以傳遞數據給 RN 的監聽
而另一個方法 Send 和 calendarEventReminderReceived ,一個是來自于官網的實例 講的是從 NSNotification獲取數據, Send 是傳遞數據給 calendarEventReminderReceived
關于監聽的優化, 這個官網上也有,有空可以看下,就是在 .m 文件中添加下列代碼:
@implementation nativeModule { bool hasListeners; // 一個局部變量 } -(void)startObserving { hasListeners = YES; } -(void)stopObserving { hasListeners = NO; } // 在發送監聽的添加判斷,如果有監聽才發送,有效減少橋接代碼的調用 if (hasListeners) { [self sendEventWithName:@"EventReminder" body:@{@"name": name}];; }
感謝各位的閱讀!關于“React Native與IOS端之間交互的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。