RN与iOS的混合开发

以前做过一个APP是纯RN开发的,还做过一个APP是RN和iOS混合开发的,现在就比较一下两者的不同。

纯RN的APP

就是通过React-Native init一个项目以后,代码写好以后把代码打包成bundle文件,然后导入到Xcode里面然后打包成ipa来发布,其中在APPdelegate里面是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;

// jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"CompassRN"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}

可以看到最重要的连接就是RCTRootView,的方法加载bundle文件,参数initialProperties必须是NSDictionary的一个实例。这一字典参数会在内部被转化为一个可供JS组件调用的JSON对象。

具体解析请看:https://www.jianshu.com/p/9d7dbf17daa5
RCTBridge桥接,moduleName是CompassRN,同样在RN中

1
2
import CompassRN from './component/Appmain';
AppRegistry.registerComponent('CompassRN', () => CompassRN);

在React Native中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类,其中RCT是ReaCT的缩写。

RN和iOS混合开发

需要在iOS工程中:

iOS是如何下载bundle文件,并且保证bundle文件的安全?

  1. TYRCTPanelViewController 的viewDidLoad中加载面板 loadDevicePanel,
    通过TYPanelService来下载面板,
    如果是debug模式的话,加载路径是:

    panelPath = [NSString stringWithFormat:@"http://%@:8081/index.ios.bundle?platform=ios&dev=true&gwId=%@",ip, self.devId];
    
    其中IP是本机电脑的IP,
    

否则release模式的话: [self loadWebView:panelPath]通过panelPath的网络请求路径来加载面板

_rootView = [[RCTRootView alloc] initWithBundleURL:[NSURL URLWithString:panelPath] moduleName:@”TYRCTApp” initialProperties:@{@”devInfo”:devInfo} launchOptions:nil];
_rootView.frame = self.view.bounds;
如果设备变更,数据,网络,蓝牙等变化的话,通过
[self.rootView.bridge.eventDispatcher sendAppEventWithName:@”networkStateChange”
body:@{@”state”:[NSNumber numberWithBool:state]}];
来通知rootView

  1. 列表中用 TYPanelViewControllerFactory来处理具体进入到哪个面板。 isEnableDebug模式下进入 TYCommonPanelViewController,

  2. TYPanelService.拉取面板主要是 TYPanelService 这个方法, 使用NSURLSessionDownload来下载面板,
    如果沙盒 TPSandBox里面通过 NSFileManager来管理,如果里面存在有面板,直接加载,
    不存在的话就去下载main.jsbundle(通过 RunLoop里面的这个方法cancelPreviousPerformRequestsWithTarget可以取消先前的请求任务)
    下载以后的面板通过JSON解析以后放到 TYUIPanel(Model)中,删除先前的tar.gz压缩包,取消先前的任务,

3.对于每一个panel文件,Model对象里面有 uiId, version, content, fileMd5,
其中 fileMd5来保证包的安全性,包解析用的工具是 TPEncryptUtils,先把 tarPath的文件转化成NSData,然后通过 DCTar来解压文件,

文章目录
  1. 1. 纯RN的APP
  2. 2. RN和iOS混合开发
本站总访问量 本站访客数人次 ,