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

Verwenden Sie PSSH zur Stapelverwaltung von Linux-Servern

pssh ist eine in Python implementierte Open-Sourc...

Nginx verwendet Lua+Redis, um IP dynamisch zu blockieren

1. Hintergrund Bei unserer täglichen Website-Wart...

Benutzererfahrung bei der Neugestaltung der Portal-Website

<br />Vom Start der neuen Homepage von NetEa...

Vue implementiert die Lupenfunktion der Produktdetailseite

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

XHTML-Erste-Schritte-Tutorial: XHTML-Hyperlinks

Es ist keine Übertreibung, zu sagen, dass Hyperlin...

Entwerfen Sie eine einfache HTML-Anmeldeoberfläche im CSS-Stil

login.html-Teil: <!DOCTYPE html> <html l...

Beispiele für die Verwendung von React Ref

Inhaltsverzeichnis Was ist ref So verwenden Sie r...

Reines CSS, um den Listen-Pulldown-Effekt auf der Seite zu erzielen

Möglicherweise sehen Sie häufig den folgenden Eff...

So zeichnen Sie eine Schaltfläche in XAML als Kreis neu

Beim Verwenden des XAML-Layouts müssen manchmal ei...