2018-02-26
react-native框架源码学习(iOS)(上)
注意事项
要学习react-native框架iOS端源码,先要了解一下注意的事项。
一、 首先需要非常熟悉objective-c语言,对OC的runtime机制更是必不可少。源码里大量用了runtime特性。然后也要熟悉c++语言。除了OC语言,里面还有大量的c++代码,OC与c++混合代码。对c++的template和std库也要熟悉。我本人对c++也熟悉,但是不够深入,对一些高级特性不是很了解,所以相关的一些代码看起来很吃力。最后当然也熟悉js语言。我大学时学习过js,但是那还真是远古时代了,js近年来发展很快,我对很多新特性不是很了解,这也对我学习有一定的阻碍。另外还有要比较了解iOS的JavaScriptCore框架,这个是js与OC通信的基础。
二、 要对react-native的版本了解。查看网上的资料时也要注意他们所说的RN版本。现在网上很多研究资料,他们所研究的版本都是很早之前的版本。新的版本跟老版本有很多细节和流程改变了。如果你发现有些文章里说的东西跟你所看到的对不上,那就是研究的版本不一致。
三、如果看不懂,多看看别人的分析文章。如果对某种语言或者框架库不熟悉,建议先把该补的补上。
我所研究的RN版本是0.49,而最新版是0.51. 最后我自己也不敢说自己完全看懂了源码,自己的理解完全正确,所以下面所说的也不一定完全正确。
核心原理
主要原理利用JavaScriptCore的通信机制来做一些基本的js和OC相互调用,但是RN还做了更多事情。
OC会将所有要暴露给JS调用的方法和属性生成一个配置表,然后会将这个配置表写入到JS端。RN中OC和JS都分别有一个桥接对象,他们相互调用都是通过这个桥接对象进行。
RN大致结构图:
启动流程
研究源码当然得从启动流程开始。新建一个RN工程,它的AppDelagte入口方法代码大致如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"VprScene"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:0.0/255 green:0.0/255 blue:0.0/255 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,别的都是普通的代码。也就是说由RCTRootView来进行整个RN的初始化。
RCTRootView的initWithBundleURL:方法中初始化了一个RCTBridge,RCTBridge的初始化方法里调用了一个setUp方法,在这里又初始化了一个RCTCxxBridge(早期版本是RCTBatchedBridge,它们都是RCTBridge的子类)对象,然后调用了它的start方法。这是个关键方法。RCTBridge与RCTCxxBridge类似一个代理模式,RCTBridge提供了对外接口,实际上调用了RCTCxxBridge的实现。这样的好处是方便替换内部实现,而接口保持稳定。
RCTCxxBridge的start方法(为了方便理解,删掉了不必要的代码):
- (void)start
{
.....