本文主要介紹包括WeexSDK-iOS主要類介紹、Weex頁面iOS端渲染流程、JS呼叫iOS方法
主要類
WXSDKEngine
WXSDKEngine主要用於初始化WeexSDK的環境
一開始會載入配置檔案main.js並且註冊一些預設的元件、模組以及handler
1 2 3 4 5 6 7 8 |
+ (void)initSDKEnviroment:(NSString *)script { [self _registerDefaultComponents]; [self _registerDefaultModules]; [self _registerDefaultHandlers]; [[WXSDKManager bridgeMgr] executeJsFramework:script]; } |
WXSDKInstance
一個WXSDKInstance就對應一個UIViewController,對應一個weex頁面。
主要用來渲染頁面,一般通過renderWithURL方法,然後能夠接收一些回撥和一些檢視相關的方法
1 2 3 4 |
onCreate //根檢視rootView建立的時候 renderFinish//檢視渲染完成 componentForRef //通過檢視索引拿到對應的元件檢視 |
WXBridgeManager
WXBridgeManager 是JS與iOS通過JSCore互動的類,相關的類還有WXBridgeContext、WXJSCoreBridge。
比如呼叫JS
1 2 3 4 5 6 7 8 9 10 |
- (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會支援實時重新整理,所以每次都需要先銷燬這個例項。
1 2 3 |
[_instance destroyInstance]; _instance = [[WXSDKInstance alloc] init]; |
然後WXSDKManager會儲存instanceId
1 2 |
[WXSDKManager storeInstance:self forID:_instanceId]; |
然後會呼叫renderWithURL方法來載入script,在這裡會判斷是本地檔案還是需要從伺服器下載,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
- (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檔案渲染檢視
1 2 |
[weakSelf renderView:script options:newOptions data:data]; |
在這個方法裡面首先會建立根檢視,當建立完成時WXSDKInstance會收到onCreate的回撥
1 2 3 4 5 6 7 8 |
//TODO WXRootView WXPerformBlockOnMainThread(^{ self.rootView = [[WXView alloc] initWithFrame:self.frame]; if(self.onCreate) { self.onCreate(self.rootView); } }); |
之後再通過bridge呼叫JS方法來開始建立例項
1 2 |
[self callJSMethod:@"createInstance" args:args]; |
然後這裡會判斷JSFramework也就是main.js有沒有載入完成,然後再通過WXJSBridge的JSContext來執行js方法
1 2 3 4 5 |
- (void)callJSMethod:(NSString *)method args:(NSArray *)args { [[_jsContext globalObject] invokeMethod:method withArguments:args]; } |
最後main.js會呼叫WXSDKInstance的createFinish方法來結束頁面的渲染
JS呼叫iOS方法
首先要註冊一個元件
1 2 |
[self registerModule:@"dom" withClass:NSClassFromString(@"WXDomModule")]; |
註冊module的時候 會通過下面方法
1 2 3 4 5 6 7 8 9 10 |
+ (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端
1 |
WX_EXPORT_METHOD(@selector(createBody:)) |
這會把方法暴露出來,並且方法名字是”wx_export_method_“加程式碼所在行號,wx_export_method_25
元件、模組 是給js端用的,而handler則是給objc自己用的,所以不用傳送訊息給js端
然後通過methodForSelector拿到WX_EXPORT_METHOD方法的返回值,並且儲存到methods中
1 2 3 4 5 6 7 8 9 |
- (void)registerModuleMethods { if ([currentClass respondsToSelector:selector]) { method = ((NSString* (*)(id, SEL))[currentClass methodForSelector:selector])(currentClass, selector); } [_methods setObject:method forKey:name]; } |
然後拿到WXModuleConfig組成的_moduleMap之後再傳送給JS端
1 2 |
[[WXSDKManager bridgeMgr] registerModules:dict]; |
最後需要自己callNative的回撥,當JS呼叫時就會傳值到這裡
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- (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的衍生品。