本文主要介绍包括WeexSDK-iOS主要类介绍、Weex页面iOS端渲染流程、JS调用iOS方法
主要类
WXSDKEngine
WXSDKEngine主要用于初始化WeexSDK的环境
一开始会载入配置文件main.js并且注册一些默认的组件、模块以及handler
+ (void)initSDKEnviroment:(NSString *)script { [self _registerDefaultComponents]; [self _registerDefaultModules]; [self _registerDefaultHandlers]; [[WXSDKManager bridgeMgr] executeJsFramework:script]; }
在executeJsFramework前,会设置后JSContext的一些回调,例如
_jsContext[@"callNative"] = callNativeBlock;
以方便JS调用native的方法。
executeJsFramework调用的是JSContext的evaluateScript方法,把main.js运行到jS的环境里面,之后再通过JSValue调用invokeMethod方法,把前面所有的components,modules,handlers注册进入JS环境
WXSDKInstance
一个WXSDKInstance就对应一个UIViewController,对应一个weex页面。
主要用来渲染页面,一般通过renderWithURL方法,然后能够接收一些回调和一些视图相关的方法
onCreate //根视图rootView创建的时候
renderFinish//视图渲染完成
componentForRef //通过视图索引拿到对应的组件视图
WXBridgeManager
WXBridgeManager 是JS与iOS通过JSCore交互的类,相关的类还有WXBridgeContext、WXJSCoreBridge。
比如调用JS
- (void)executeJsMethod:(WXBridgeMethod *)method
{
if (!method) return;
__weak typeof(self) weakSelf = self;
WXPerformBlockOnBridgeThread(^(){
[weakSelf.bridgeCtx executeJsMethod:method];
});
}
JS调用native的话需要通过WXJSCoreBridge的registerCallNative方法
WXComponent
组件基类,自己实现iOS端的组件需要继承它。相关的还有负责组件初始化的工厂类WXComponentFactory,以及WXComponentManager
WXModuleProtocol
自定义module需要实现的协议
weex页面iOS端渲染流程
首先在ViewController里的render放初始化WXSDKInstance,因为render会支持实时刷新,所以每次都需要先销毁这个实例。
[_instance destroyInstance];
_instance = [[WXSDKInstance alloc] init];
然后WXSDKManager会保存instanceId
[WXSDKManager storeInstance:self forID:_instanceId];
然后会调用renderWithURL方法来载入script,在这里会判断是本地文件还是需要从服务器下载,
- (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data{
if ([url isFileURL]) {
//from local
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *path = [url path];
NSData *scriptData = [[NSFileManager defaultManager] contentsAtPath:path];
NSString *script = [[NSString alloc] initWithData:scriptData encoding:NSUTF8StringEncoding];
[weakSelf renderView:script options:newOptions data:data];
});
}else{
//from server
}
}
然后就会根据script文件渲染视图
[weakSelf renderView:script options:newOptions data:data];
在这个方法里面首先会创建根视图,当创建完成时WXSDKInstance会收到onCreate的回调
//TODO WXRootView
WXPerformBlockOnMainThread(^{
self.rootView = [[WXView alloc] initWithFrame:self.frame];
if(self.onCreate) {
self.onCreate(self.rootView);
}
});
之后再通过bridge调用JS方法来开始创建实例
[self callJSMethod:@"createInstance" args:args];
然后这里会判断JSFramework也就是js有没有加载完成,然后再通过WXJSBridge的JSContext来执行js方法,这里调用的就是js的createInstance方法,args里面主要就是instanceID,we文件转化的js文件,和options。
- (void)callJSMethod:(NSString *)method args:(NSArray *)args
{
[[_jsContext globalObject] invokeMethod:method withArguments:args];
}
最后js会调用JSContext的callCreateFinish回调,最后调用WXSDKInstance的createFinish方法来结束页面的渲染
JS调用iOS方法
首先要注册一个组件
[self registerModule:@"dom" withClass:NSClassFromString(@"WXDomModule")];
注册module的时候 会通过下面方法
+ (void)registerModule:(NSString *)name withClass:(Class)clazz
{
WXAssert(name && clazz, @"Fail to register the module, please check if the parameters are correct !");
NSString *moduleName = [WXModuleFactory registerModule:name withClass:clazz];
NSDictionary *dict = [WXModuleFactory moduleMethodMapsWithName:moduleName];
[[WXSDKManager bridgeMgr] registerModules:dict];
}
把所有通过宏注册的方法发送给js端
WX_EXPORT_METHOD(@selector(createBody:))
这会把方法暴露出来,并且方法名字是”wx_export_method_“加代码所在行号,wx_export_method_25
组件、模块 是给js端用的,而handler则是给objc自己用的,所以不用发送消息给js端
然后通过methodForSelector拿到WX_EXPORT_METHOD方法的返回值,并且保存到methods中
- (void)registerModuleMethods {
if ([currentClass respondsToSelector:selector]) {
method = ((NSString* (*)(id, SEL))[currentClass methodForSelector:selector])(currentClass, selector);
}
[_methods setObject:method forKey:name];
}
然后拿到WXModuleConfig组成的_moduleMap之后再发送给JS端
[[WXSDKManager bridgeMgr] registerModules:dict];
这里就是前面提到的调用JSContext的invokeMethod把内容发送到JS端
最后需要自己callNative的回调,当JS调用时就会传值到这里
- (void)registerCallNative:(WXJSCallNative)callNative
{
NSInteger (^callNativeBlock)(JSValue *, JSValue *, JSValue *) = ^(JSValue *instance, JSValue *tasks, JSValue *callback){
NSString *instanceId = [instance toString];
NSArray *tasksArray = [tasks toArray];
NSString *callbackId = [callback toString];
return callNative(instanceId, tasksArray, callbackId);
};
_jsContext[@"callNative"] = callNativeBlock;
}
tasks里面包括方法的一些相关信息,包括module(比如dom),method(比如updateFinish),args
weex-devtool-iOS
weex-devtool-iOS 其实是 PonyDebugger的衍生品。