Detaillierte Erklärung der Interaktion zwischen React Native und IOS

Detaillierte Erklärung der Interaktion zwischen React Native und IOS

Voraussetzungen

Zunächst einmal ist es am besten, ein wenig über die Grammatik von oc zu verstehen

1. Erstellen Sie eine Deklarationsdatei nativeModule.h

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

@interface nativeModule : NSObject <RCTBridgeModule>

@Ende

2. Erstellen Sie die Datei nativeModule.m

#importieren <Foundation/Foundation.h>
#importiere "nativeModule.h"

@Schnittstelle nativeModule ()

@Ende

@implementierung nativesModul

@Ende 

Dies ist die Verzeichnisstruktur nach dem Hinzufügen der Datei.

Über den Unterschied der Schnittstelle:

Das @interface in .h wird von anderen Klassen zum Aufrufen verwendet. Seine @property und Funktionen können von anderen Klassen „gesehen“ werden (öffentlich)

Das @interface in .m wird in OC als Klassenerweiterung bezeichnet und ist eine Ergänzung zum @interface in der .h-Datei. Das @interface in der .m-Datei ist jedoch nicht für die Außenwelt zugänglich und nur in der .m-Datei sichtbar (privat).

Daher fügen wir die Methoden und Variablen, die für die Außenwelt zugänglich sind, in die H-Datei ein und die Variablen, die wir nicht für die Außenwelt öffnen möchten, in die M-Datei (die Methoden in der M-Datei können direkt ohne Deklaration verwendet werden).

RN übergibt Wert an iOS

Methode 1: Wert normal an native übergeben

Fügen Sie der .m-Datei die folgende Methode hinzu:

//Den obigen Code weglassen @implementation nativeModule

// Dieser Code wird benötigt, um das Modul zu exportieren, damit auf das Modul nativeModule in RN zugegriffen werden kann
RCT_EXPORT_MODULE();

// Zeichenfolge empfangen RCT_EXPORT_METHOD(addHelloWord:(NSString *)name location:(NSString *)location)
{
  NSLog(@"%@,%@", Name, Ort);
}
@Ende

RN-Code:

importiere { Button, NativeModules } von 'react-native'
const { nativeModul } = NativeModule

<Button title={'Übergeben Sie 2 Parameter an native'} onPress={() => {
    nativeModule.addHelloWord('Ihr Name', 'Standort: Zhejiang')
}}/>

Wenn Sie auf diese Schaltfläche klicken, werden die beiden Zeichenfolgen „Ihr Name“ und „Standort: Zhejiang“ an die native Seite übergeben.

Methode 2: Übergeben einer Rückruffunktion

Fügen Sie der .m-Datei Folgendes hinzu:

// Akzeptiert nur einen Parameter – ein Array von Parametern, die an die JavaScript-Rückruffunktion übergeben werden sollen.
RCT_EXPORT_METHOD(checkIsRoot:(RCTResponseSenderBlock)Rückruf) {
  NSArray *array = @[@"Zeichenfolge", @"Zahl"];
  Rückruf (Array);
}

Code in RN hinzufügen:

<Button title={'js übergibt einen Rückruf an native und empfängt ein Array im Rückruf'} onPress={() => {
    nativeModule.checkIsRoot((str: string, num: string) => {
      console.log(str, num)
    })
}}/>

Dies ist eine Rückruffunktion, die an das native Ende in RN übergeben wird, um den Rückruf nach Abschluss einiger Vorgänge zu lösen. **Wenn der Rückruf mehrmals aufgerufen wird, meldet RN einen Fehler**

Methode 3: Promise-Callback erhalten

Fügen Sie der .m-Datei den folgenden Code hinzu:

@Schnittstelle nativeModule ()

@property (nichtatomar) RCTPromiseResolveBlock normalResolve;
@property (nichtatomar) RCTPromiseRejectBlock normalReject;
@property (nichtatomar) NSInteger num;

@Ende


// Dies ist ein Timer - (void)startTime: (NSArray*) data{
  NSTimer *Timer = [NSTimer scheduledTimerWithTimeInterval:2 Wiederholungen:JA Block:^(NSTimer * _Nonnull Timer) {
    
    NSArray *Ereignisse =@[@"Versprechen ",@"Test ",@"Array"];
    wenn (Ereignisse) {
      self.normalResolve(Ereignisse);
      [Timer ungültig machen];
    } anders {
      [Timer ungültig machen];
      NSError *error=[NSError errorWithDomain:@"Ich rufe die Fehlermeldung zurück..." code:101 userInfo:nil];
      self.normalReject(@"no_events", @"Es gab keine Ereignisse", Fehler);
    }
  }];
  
  [[NSRunLoop mainRunLoop] addTimer:Timer fürModus:NSDefaultRunLoopMode];
}

// Rückrufparameter an RN, Rückruffehlerinformationen RCT_EXPORT_METHOD(getHBDeviceUniqueID: (RCTPromiseResolveBlock)resolve
                  Ablehner:(RCTPromiseRejectBlock)Ablehnen) {
  
  // Auszuführende Aufgabe self.normalResolve = resolve;
  self.normalReject = ablehnen;
  
  [selbst performSelectorOnMainThread:@selector(startTime:) mitObjekt: [NSArray arrayWithObjects: @"1", @"2", nil] wartebisFertig:JA];
}

Code in RN hinzufügen:

<Button title={'native übergibt ein Versprechen an JS'} onPress={() => {
    nativeModule.getHBDeviceUniqueID().then((arr: string[]) => {
      console.log('auflösen', arr)
    }).catch((err: Zeichenfolge) => {
      console.error(fehler)
    })
}}/>

Die Ausführung von nativeModule.getHBDeviceUniqueID ist ein Versprechen, das den Rückruf des nativen Endes abrufen kann, was tatsächlich Methode 2 ähnelt.

Methode 4: Synchroner Weg, um ein Versprechen zu erhalten

Fügen Sie der .m-Datei Folgendes hinzu:

// Dies ist ein Timer 2
-(void)startTime2: (NSArray*) Daten{
  NSLog(@"Daten%@",Daten);
  
  NSTimer *Timer = [NSTimer scheduledTimerWithTimeInterval:1 Wiederholungen:JA Block:^(NSTimer * _Nonnull Timer) {
    
    NSLog(@"%d", (int)self.num);
    
    selbst.num = selbst.num + 1;
    
    NSLog(@"%d", (int)self.num);
    
    wenn (selbst.zahl > 4) {
      [Timer ungültig machen];
      NSLog(@"Ende");
      selbst.normalResolve(Daten);
    }
    
  }];
  
  [[NSRunLoop mainRunLoop] addTimer:Timer fürModus:NSDefaultRunLoopMode];
}

// RCT_REMAP_METHOD ist dasselbe wie RCT_EXPORT_METHOD, aber diese Methode wird synchron von JS im JS-Thread aufgerufen und kann ein Ergebnis zurückgeben.
// Bei der Synchronisierung können Leistungsprobleme auftreten. Es wird empfohlen, RCT_REMAP_METHOD(findEvents,
                 findEventsWithResolver:(RCTPromiseResolveBlock)auflösen
                 Ablehner:(RCTPromiseRejectBlock)Ablehnen)
{
  self.normalResolve = auflösen;
  self.normalReject = ablehnen;
  
  
  selbst.num = 0;
  
  [selbst performSelectorOnMainThread:@selector(startTime2:) mitObject: [NSArray arrayWithObjects: @"1", @"2", nil] wartebisFertig:JA];
}

Code auf der RN-Seite hinzufügen:

<Button title={'native übergibt ein Versprechen an JS2'} onPress={() => {
    nativeModule.findEvents().then((arr: string[]) => {
      console.log('auflösen', arr)
    }).catch((err: Zeichenfolge) => {
      console.error(fehler)
    })
}}/>

Methode 4 ist im Wesentlichen dieselbe wie Methode 3, es gibt jedoch einen Unterschied: RCT_REMAP_METHOD verwendet diese Methode, um den Code in einen synchronen Zustand zu versetzen.

iOS übergibt Wert an RN-Ende

Erstdatenbereitstellung

Fügen Sie appDelegate.m den folgenden Code hinzu:

NSArray *imageList = @[@"http://foo.com/bar1.png",
                @"http://foo.com/bar2.png"];

NSDictionary *props = @{@"images" : Bilderliste};


RCTRootView *rootView = [[RCTRootView-Zuweisung] initWithBridge:bridge moduleName:@"learn" initialProperties:props];
// Diese Codezeile existiert bereits, der Unterschied ist initialProperties:props

Schreiben Sie auf die RN-Seite:

// APP neu schreiben, Bilder sind die von iOS bereitgestellten Daten, hier übergeben wir die Daten durch Kontextexport Standardklasse App erweitert React.Component<{ images: string[] }> {

  rendern() {
    gibt <NativeProps.Provider-Wert={this.props.images}> zurück
      <AppContainer/>
    </NativeProps.Provider>
  }
}

// Einfach in Hooks verwenden const images = useContext(NativeProps);

<Text>Dies sind die ursprünglichen Daten von der nativen Seite {JSON.stringify(images)}</Text>

Hinzufügen von Ereignis-Listenern

Fügen Sie der .m-Datei den folgenden Code hinzu:

// Zur Überwachung verfügbare Ereignisnamen - (NSArray<NSString *> *)supportedEvents
{
  Rückkehr @[@"EventReminder"];
}


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

- (void)calendarEventReminderReceived:(NSNotification *)Benachrichtigung
{
  // Dies ist ein Beispiel von der offiziellen Website NSLog(@"calendarEventReminderReceived");
  NSString *eventName = Benachrichtigung.Benutzerinfo[@"Name"];
  [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}

RCT_EXPORT_METHOD(Senden){
  NSDictionary *dict = @{@"name" : @"veuimyzi"};
  
  NSNotification *Benachrichtigung = [[NSNotification alloc] initWithName:@"EventReminder" Objekt:nil Benutzerinfo:dict];
  
  [selbst KalenderEventReminderReceived:Benachrichtigung];
}

Code in RN hinzufügen:

const ManagerEmitter = neuer NativeEventEmitter(nativeModule)

const [msg, setMsg] = useState([])

// In Hooks verwenden, ähnlich dem Lebenszyklus von componentDidMount useEffect(() => {
    const Abonnement = ManagerEmitter.addListener(
      'EventErinnerung',
      (Erinnerung) => {
        setMsg(vorherigerStatus => {
          Rückgabewert für vorherigen Status.concat(Erinnerung.Name)
        })
        console.log('Dies ist die überwachte EventReminder-Ereignisantwort', reminder.name)
      }
    )

    zurückgeben () => {
      Abonnement.entfernen()
    }
}, [])


<Button title={'js hört auf Ereignisse, lasst native Benachrichtigungen an js senden'} onPress={() => {
    nativeModule.postNotificationEvent('test')
}}/>

<Button title={'js hört auf Ereignisse, lasst native Benachrichtigungen an js senden'} onPress={() => {
    nativeModule.Senden()
}}/>

{
    msg.map((Element, Index) => {
      gibt <Textschlüssel={Element + Index}>Element:{Element}</Text> zurück
    })
}

Die Methode postNotificationEvent ist am einfachsten zu verwenden. Durch Aufrufen von sendEventWithName auf der nativen Seite können Daten an den RN-Listener übergeben werden.

Die andere Methode ist Send und calendarEventReminderReceived. Eine davon ist von der offiziellen Website. Das Beispiel dient zum Abrufen von Daten von NSNotification und Send übergibt Daten an calendarEventReminderReceived.

Zur Optimierung der Überwachung gibt es auch einen Link auf der offiziellen Website. Sie können ihn sich ansehen, wenn Sie Zeit haben. Fügen Sie einfach den folgenden Code zur .m-Datei hinzu:

@implementierung nativesModul
{
  bool hatListeners;
  // eine lokale Variable }

-(void)startObserving {
  hatListeners = JA;
}

-(void)stopObserving {
  hasListeners = NEIN;
}
// Beim Senden von Listenern Urteilsvermögen hinzufügen. Nur senden, wenn Listener vorhanden sind, wodurch die Aufrufe des Bridge-Codes effektiv reduziert werden, if (hasListeners) { 
    [self sendEventWithName:@"EventReminder" body:@{@"name": name}];;
}

Zusammenfassen

Das Repository für den obigen Code: https://github.com/Grewer/learn-rn

Das ist im Wesentlichen alles zur Interaktion zwischen der nativen Seite und der RN-Seite. Natürlich gibt es auf der nativen Seite immer komplexere Operationen, wie z. B. Prozesse. Wenn Sie eine Bridge-Methode schreiben möchten, werden Sie häufig darauf stoßen. Die Beherrschung der oben genannten Punkte reicht jedoch aus, um einige SDKs von Drittanbietern aufzurufen.

Oben finden Sie eine ausführliche Erläuterung der Interaktion zwischen React Native und IOS. Weitere Informationen zur Interaktion zwischen React Native und IOS finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • React Axios - domänenübergreifender Zugriff auf einen oder mehrere Domänennamen
  • Reactnative-iOS-Callback-Javascript-Methode
  • So implementieren Sie differenzielle inkrementelle Updates für React Native unter iOS
  • So kombinieren Sie NavigatorIOS und ListView in React-Native-Komponenten
  • Beispielcode für verschiedene Interaktionen zwischen iOS native und react-native
  • Beispiele für die gemeinsame Nutzung von React Native-Plattformen von Drittanbietern (Android, iOS-Dualplattform)
  • Lösung für das Problem, dass IOS React und andere Titel nicht angezeigt werden
  • React-Native Android und IOS App verwenden einen Code zur Implementierung
  • IOS React Native FlexBox: Ausführliche Erklärung und Beispiele

<<:  Detaillierte Erklärung gängiger Befehle im Docker-Repository

>>:  Tutorial zum Erstellen des File-Sharing-Dienstes Samba unter CentOS6.5

Artikel empfehlen

Detaillierte Erklärung zur Verwendung von Echarts-Maps in Angular

Inhaltsverzeichnis Initialisierung von Echart App...

Analyse und Anwendung des Wasserfallflussprinzips unregelmäßiger Bilder

Das im Projekt aufgetretene Layoutproblem unregel...

Vue implementiert das Senden von Emoticons im Chatfenster

Der spezifische Code zum Senden von Emoticons im ...

mysql 8.0.19 winx64.zip Installations-Tutorial

Dieser Artikel zeichnet das Installationstutorial...

Vue implementiert einen Wasserfallfluss mit unendlichem Laden

In diesem Artikelbeispiel wird der spezifische Co...

Setzen Sie den Eingang auf schreibgeschützt über deaktiviert und schreibgeschützt

Es gibt zwei Möglichkeiten, schreibgeschützte Eing...

17 hervorragende Webdesigns, sorgfältig von Startups entwickelt

Startups überraschen uns oft mit ihren unkonventi...

Docker ermöglicht mehrere Port-Mapping-Befehle

wie folgt: docker run -d -p 5000:23 -p 5001:22 --...

js canvas realisiert Bilder mit abgerundeten Ecken

In diesem Artikel wird der spezifische Code von J...

So kapseln Sie Abfragekomponenten basierend auf Element-UI Schritt für Schritt

Inhaltsverzeichnis Funktion Grundlegende Abfragef...

Vue implementiert die Anmeldung per Mobiltelefon-Bestätigungscode

In diesem Artikel wird der spezifische Code von V...

Implementierung der automatischen Konstruktionsweiterleitung von React

Inhaltsverzeichnis Sequenz 1. Zentralisiertes Rou...

Umfassende Analyse der Isolationsebenen in MySQL

Wenn die Datenbank gleichzeitig denselben Datenst...

So zählen Sie das Datum mit Bash herunter

Sie möchten wissen, wie viele Tage es bis zu eine...