Each language has its own design concept, syntax and running environment, which also leads to the need for intermediaries to translate when communicating between different languages. For example, JAVA and C/C + + communicate through JNI, OC and C/C + + need to be translated in mm files are mixed, and the communication between JAVA/OC and Lua needs to be mediated by C/C + + language. So how does JSX communicate with the underlying modules in react native? This is mainly explained by iOS system.
principle
Communication is essentially the exchange of information, and computer language is the flow of data. The flow and sharing of data between react native and native modules in the application completes the interaction with users and achieves the goal of the application. The data communicated between react native and OC can only be of the following types (JS before OC):
- string-NSString
- number - int/NSInteger/float/double/NSNumber
- boolean - BOOL/NSNumber
- array - NSArray
- object - NSDictionary(NSString type key and value can be other types here)
- func - RCTResponseSenderBlock
Other types of data need to be converted into these types (usually into JSON strings) through certain rules before communication
The essence of react native is through JavaScript core Framework realizes the interaction between JS code and OC code. Therefore, the essential principles of the following methods are the same, and the difference lies in the difference of implementation forms and methods.
function call
When the native module is encapsulated and provided to react native for use, you can use RCT_ EXPORT_ The method () macro defines the interface functions it can call to the react native side to complete the communication between the two modules.
//The startVPN interface is defined. React native transmits the specific parameters of VPN to the native module through this interface to start the specified VPN RCT_EXPORT_METHOD(startVPN:(NSDictionary*)config) { LSShadowSocksDataMode* mode = [[LSShadowSocksDataMode alloc] initWithDictionary:config]; [self.manager startVPN:mode]; }
In addition to incoming data, data can be obtained from the native side in this way. The easiest thing to think of is to get through the return value. Unfortunately, RCT_EXPORT_METHOD macros do not support return values, but they provide another way to implement return values:
RCT_EXPORT_METHOD(isOpen:(RCTResponseSenderBlock)callback) { BOOL open = [self.manager status]; callback(@[[NSNull null], @[@(open)]]); }
The effect of return value is realized in the form of callback function to achieve the purpose of data exchange.
Attribute sharing
This method is mainly for UI controls. The most basic UI type in react native is RCTRootView. This class has an initialization method initWithBridge:moduleName:initialProperties:, and the third parameter initialProperties represents the initial property value of the UI control. The type is NSDictionary, which will eventually be synchronized to the props of react native class defined by the second parameter, That is, the data exchange between the two modules is completed.
NSArray *imageList = @[@"http://foo.com/bar1.png", @"http://foo.com/bar2.png"]; NSDictionary *props = @{@"images" : imageList}; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"ImageBrowserApp" initialProperties:props];
import React, { Component } from 'react'; import { AppRegistry, View, Image, } from 'react-native'; class ImageBrowserApp extends Component { renderImage(imgURI) { return ( <Image source={{uri: imgURI}} /> ); } render() { return ( <View> {this.props.images.map(this.renderImage)} </View> ); } } AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);
The initialization interface can only be used when the UI component is established. What if it needs to communicate within the life cycle of the UI component, RCTRootView provides a mechanism such as appProperties:
NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
notice
In OC, the NSNotificationCenter is used to send notifications to the entire application. All objects interested in the notification will get the notification and perform corresponding actions. A similar mechanism is provided in react native: RCTEventEmitter. After inheriting this class, the native module can send a notification to the react native side, and react native can receive the notification and process the data transmitted together.
-(void)vpnStatusChanged:(NSNotification*)notification { NEVPNStatus status = [self.manager status]; NSString* value = nil; switch (status) { case NEVPNStatusReasserting: value = @"Reconnecting"; break; case NEVPNStatusConnecting: value = @"Connecting"; break; case NEVPNStatusConnected: value = @"Connected"; break; case NEVPNStatusDisconnecting: value = @"Disconnecting"; break; case NEVPNStatusDisconnected: case NEVPNStatusInvalid: value = @"End connection"; break; default: break; } if(value){ [self sendEventWithName:@"VpnStatus" body:@{@"status":value}]; } }
Here, the status of V * * is sent to the react native side through notification, and react native displays the status of V * * on the UI interface.