最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解React Native與IOS端之間的交互

 更新時間:2021年06月03日 14:22:45   作者:Grewer  
React Native (簡稱RN)是Facebook于2015年4月開源的跨平臺移動應用開發(fā)框架,是Facebook早先開源的JS框架 React 在原生移動應用平臺的衍生產(chǎn)物,支持iOS和安卓兩大平臺。本文將介紹React Native與IOS端之間的交互。

前置準備

首先最好了解一點關于 oc 的語法知識

1.創(chuàng)建聲明文件nativeModule.h

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface nativeModule : NSObject <RCTBridgeModule>

@end

2.創(chuàng)建文件nativeModule.m

#import <Foundation/Foundation.h>
#import "nativeModule.h"

@interface nativeModule ()

@end

@implementation nativeModule

@end

這是添加完文件后的結(jié)構(gòu)目錄

關于 interface 的區(qū)別:

.h里面的@interface,它是供其它Class調(diào)用的。它的@property和functions,都能夠被其它Class“看到”(public)

而.m里面的@interface,在OC里叫作Class Extension,是.h文件中@interface的補充。但是.m文件里的@interface,對外是不開放的,只在.m文件里可見(private)

因此,我們將對外開放的方法、變量放到.h文件中,而將不想要對外開放的變量放到.m文件中(.m文件的方法可以不聲明,直接用)。

RN 傳值給 iOS

方法 1 正常傳值給原生

在 .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 個參數(shù)給 native'} onPress={() => {
    nativeModule.addHelloWord('你的名字', '位置:浙江')
}}/>

點擊此按鈕的作用,就是將 '你的名字', '位置:浙江' 這 2 個字符串傳遞到了原生端

方法 2 傳遞回調(diào)函數(shù)

在 .m 文件中添加:

// 只接受一個參數(shù)——傳遞給 JavaScript 回調(diào)函數(shù)的參數(shù)數(shù)組。
RCT_EXPORT_METHOD(checkIsRoot:(RCTResponseSenderBlock)callback) {
  NSArray *array = @[@"string", @"number"];
  callback(array);
}

在 RN 中添加代碼:

<Button title={'js 傳一個回調(diào)給 native,回調(diào)中收到一個數(shù)組'} onPress={() => {
    nativeModule.checkIsRoot((str: string, num: string) => {
      console.log(str, num)
    })
}}/>

這是在 RN 中 給原生端傳遞了一個回調(diào)函數(shù),用來解決,部分操作完成后的回調(diào), ** 如果 callback 多次調(diào)用 RN 會報錯 **

方法 3 獲取 promise 回調(diào)

在 .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:@"我是回調(diào)錯誤信息..." code:101 userInfo:nil];
      self.normalReject(@"no_events", @"There were no events", error);
    }
  }];
  
  [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}

// 回調(diào)給RN的參數(shù),回調(diào)的錯誤信息
RCT_EXPORT_METHOD(getHBDeviceUniqueID: (RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
  
  // 要執(zhí)行的任務
  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 的執(zhí)行他是一個 promise,可以獲取原生端的回調(diào), 其實和方法 2 差不多

方法 4 獲取 promise 的同步方式

在 .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同步調(diào)用的,可能會返回結(jié)果。
// 同步可能會有性能問題  建議除了 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 使用此方法會將代碼變成同步狀態(tài)

iOS 傳值給 RN 端

初始的數(shù)據(jù)提供

在 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 提供的數(shù)據(jù),這里我們通過 context 來傳遞數(shù)據(jù)
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 端傳來的初始數(shù)據(jù){JSON.stringify(images)}</Text>

添加監(jiān)聽事件

在 .m 文件中添加代碼:

// 可供監(jiān)聽的事件名稱
- (NSArray<NSString *> *)supportedEvents
{
  return @[@"EventReminder"];
}


RCT_EXPORT_METHOD(postNotificationEvent:(NSString *)name)
{
  NSLog(@"calendarEventReminderReceived");
    [self sendEventWithName:@"EventReminder" body:@{@"name": name}];;
}

- (void)calendarEventReminderReceived:(NSNotification *)notification
{
  // 這是官網(wǎng)的例子
  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('這是監(jiān)聽的EventReminder事件回復', reminder.name)
      }
    )

    return () => {
      subscription.remove()
    }
}, [])


<Button title={'js 監(jiān)聽事件,讓 native 給 js 發(fā)通知'} onPress={() => {
    nativeModule.postNotificationEvent('test')
}}/>

<Button title={'js 監(jiān)聽事件,讓 native 給 js 發(fā)通知 send'} onPress={() => {
    nativeModule.Send()
}}/>

{
    msg.map((item, index) => {
      return <Text key={item + index}>item:{item}</Text>
    })
}

關于 postNotificationEvent 方法是屬于最簡單的使用, 在原生端調(diào)用 sendEventWithName 就可以傳遞數(shù)據(jù)給 RN 的監(jiān)聽

而另一個方法 Send 和 calendarEventReminderReceived ,一個是來自于官網(wǎng)的實例 講的是從 NSNotification獲取數(shù)據(jù), Send 是傳遞數(shù)據(jù)給 calendarEventReminderReceived

關于監(jiān)聽的優(yōu)化, 這個官網(wǎng)上也有,有空可以看下,就是在 .m 文件中添加下列代碼:

@implementation nativeModule
{
  bool hasListeners;
  // 一個局部變量
}

-(void)startObserving {
  hasListeners = YES;
}

-(void)stopObserving {
  hasListeners = NO;
}
// 在發(fā)送監(jiān)聽的添加判斷,如果有監(jiān)聽才發(fā)送,有效減少橋接代碼的調(diào)用
if (hasListeners) { 
    [self sendEventWithName:@"EventReminder" body:@{@"name": name}];;
}

總結(jié)

上述代碼的庫: https://github.com/Grewer/learn-rn

關于原生端和 RN 端的交互基本就是這些了,當然原生端還有更多,更復雜的操作,比如進程什么的,如果想寫橋接方法,這個也會碰到很多,不過掌握了上面這些,對于一些三方 SDK 的調(diào)用是夠用了

以上就是詳解React Native與IOS端之間的交互的詳細內(nèi)容,更多關于React Native與IOS端之間的交互的資料請關注腳本之家其它相關文章!

相關文章

  • react實現(xiàn)路由攔截的示例代碼

    react實現(xiàn)路由攔截的示例代碼

    這篇文章主要介紹react實現(xiàn)路由攔截的,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-02-02
  • react的context和props詳解

    react的context和props詳解

    這篇文章主要介紹了react的context和props的相關資料,幫助大家更好的理解和學習使用React,感興趣的朋友可以了解下
    2021-11-11
  • React?錯誤邊界Error?Boundary使用示例解析

    React?錯誤邊界Error?Boundary使用示例解析

    這篇文章主要為大家介紹了React?錯誤邊界Error?Boundary使用示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 淺談React原生APP更新

    淺談React原生APP更新

    當一個APP在運行的時候, 開發(fā)者想要將自己的代碼更新到用戶的手機上時, 一般都有兩種方案, 一是熱更新, 二就是APP更新.熱更新暫且不說,這篇文章就講講 APP 如何更新。
    2021-06-06
  • React中state屬性案例詳解

    React中state屬性案例詳解

    在React中,state 是一個用于存儲組件內(nèi)部數(shù)據(jù)的特殊對象,每個React組件都可以包含自己的state,我們往往是通過修改state的值來驅(qū)動React重新渲染組件,這篇文章主要介紹了React中state屬性,需要的朋友可以參考下
    2023-11-11
  • react基于Ant Desgin Upload實現(xiàn)導入導出

    react基于Ant Desgin Upload實現(xiàn)導入導出

    本文主要介紹了react基于Ant Desgin Upload實現(xiàn)導入導出,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-01-01
  • GraphQL在react中的應用示例詳解

    GraphQL在react中的應用示例詳解

    這篇文章主要為大家介紹了GraphQL在react中的應用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React的生命周期函數(shù)初始掛載更新移除詳解

    React的生命周期函數(shù)初始掛載更新移除詳解

    這篇文章主要為大家介紹了React的生命周期函數(shù)初始掛載更新移除詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • React Native中的RefreshContorl下拉刷新使用

    React Native中的RefreshContorl下拉刷新使用

    本篇文章主要介紹了React Native中的RefreshContorl下拉刷新使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • React高級特性Context萬字詳細解讀

    React高級特性Context萬字詳細解讀

    React的context就是一個全局變量,可以從根組件跨級別在React的組件中傳遞。React context的API有兩個版本,React16.x之前的是老版本的context,之后的是新版本的context
    2022-11-11

最新評論

固阳县| 南陵县| 烟台市| 城固县| 长沙县| 上杭县| 湛江市| 来安县| 云龙县| 唐河县| 高要市| 鹤庆县| 永吉县| 锡林浩特市| 胶南市| 双柏县| 新密市| 张掖市| 贡山| 博爱县| 濮阳县| 牙克石市| 白沙| 时尚| 大洼县| 饶平县| 朝阳市| 博野县| 乌鲁木齐市| 富平县| 阿鲁科尔沁旗| 湖北省| 双辽市| 镇赉县| 元阳县| 岱山县| 陕西省| 南投县| 四会市| 徐州市| 友谊县|