源码
初始化环境 [WXSDKEngine initSDKEnvironment] 做了哪些?
//有筛减
+ (void)initSDKEnvironment
{
//加载本地的一个js文件,并且以参数的形式 传给sdk
NSString *fileName = @"weex-main-jsfm";
NSString *filePath = [[NSBundle bundleForClass:self] pathForResource:fileName ofType:@"js"];
if (filePath == nil) {
filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"js"];
}
NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
[WXSDKEngine initSDKEnvironment:script];
...//(配置模拟器相关代码)
}
[WXSDKEngine initSDKEnvironment:script]; 做了什么?
+ (void)initSDKEnvironment:(NSString *)script
{
WX_MONITOR_PERF_START(WXPTInitalize)
WX_MONITOR_PERF_START(WXPTInitalizeSync)
if (!script || script.length <= 0) {
NSMutableString *errMsg = [NSMutableString stringWithFormat:@"[WX_KEY_EXCEPTION_SDK_INIT_JSFM_INIT_FAILED] script don't exist:%@",script];
[WXExceptionUtils commitCriticalExceptionRT:@"WX_KEY_EXCEPTION_SDK_INIT" errCode:[NSString stringWithFormat:@"%d", WX_KEY_EXCEPTION_SDK_INIT] function:@"initSDKEnvironment" exception:errMsg extParams:nil];
WX_MONITOR_FAIL(WXMTJSFramework, WX_ERR_JSFRAMEWORK_LOAD, errMsg);
return;
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self registerDefaults];//注册内容
[[WXSDKManager bridgeMgr] executeJsFramework:script];//执行JSFramwork
});
WX_MONITOR_PERF_END(WXPTInitalizeSync)
}
WX_MONITOR_FAIL(WXMTJSFramework, WX_ERR_JSFRAMEWORK_LOAD, errMsg);
从这句话可以看出来 JSFramwork 指的是 这个本地weex-main-jsfm.js 文件
registerDefaults 注册了那些东西
+ (void)registerDefaults
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self _registerDefaultComponents];//默认的控件
[self _registerDefaultModules];//默认模块
[self _registerDefaultHandlers];//默认的handler
});
}
_registerDefaultComponents 具体注册了什么
// register some default components when the engine initializes.
+ (void)_registerDefaultComponents
{
[self registerComponent:@"container" withClass:NSClassFromString(@"WXDivComponent") withProperties:nil];
[self registerComponent:@"div" withClass:NSClassFromString(@"WXComponent") withProperties:nil];
[self registerComponent:@"text" withClass:NSClassFromString(@"WXTextComponent") withProperties:nil];
[self registerComponent:@"image" withClass:NSClassFromString(@"WXImageComponent") withProperties:nil];
[self registerComponent:@"richtext" withClass:NSClassFromString(@"WXRichText") withProperties:nil];
[self registerComponent:@"scroller" withClass:NSClassFromString(@"WXScrollerComponent") withProperties:nil];
[self registerComponent:@"list" withClass:NSClassFromString(@"WXListComponent") withProperties:nil];
[self registerComponent:@"recycler" withClass:NSClassFromString(@"WXRecyclerComponent") withProperties:nil];
[self registerComponent:@"waterfall" withClass:NSClassFromString(@"WXRecyclerComponent") withProperties:nil];
[self registerComponent:@"header" withClass:NSClassFromString(@"WXHeaderComponent")];
[self registerComponent:@"cell" withClass:NSClassFromString(@"WXCellComponent")];
[self registerComponent:@"embed" withClass:NSClassFromString(@"WXEmbedComponent")];
[self registerComponent:@"a" withClass:NSClassFromString(@"WXAComponent")];
[self registerComponent:@"select" withClass:NSClassFromString(@"WXSelectComponent")];
[self registerComponent:@"switch" withClass:NSClassFromString(@"WXSwitchComponent")];
[self registerComponent:@"input" withClass:NSClassFromString(@"WXTextInputComponent")];
[self registerComponent:@"video" withClass:NSClassFromString(@"WXVideoComponent")];
[self registerComponent:@"indicator" withClass:NSClassFromString(@"WXIndicatorComponent")];
[self registerComponent:@"slider" withClass:NSClassFromString(@"WXCycleSliderComponent")];
[self registerComponent:@"cycleslider" withClass:NSClassFromString(@"WXCycleSliderComponent")];
[self registerComponent:@"web" withClass:NSClassFromString(@"WXWebComponent")];
[self registerComponent:@"loading" withClass:NSClassFromString(@"WXLoadingComponent")];
[self registerComponent:@"loading-indicator" withClass:NSClassFromString(@"WXLoadingIndicator")];
[self registerComponent:@"refresh" withClass:NSClassFromString(@"WXRefreshComponent")];
[self registerComponent:@"textarea" withClass:NSClassFromString(@"WXTextAreaComponent")];
[self registerComponent:@"canvas" withClass:NSClassFromString(@"WXCanvasComponent")];
[self registerComponent:@"slider-neighbor" withClass:NSClassFromString(@"WXSliderNeighborComponent")];
[self registerComponent:@"recycle-list" withClass:NSClassFromString(@"WXRecycleListComponent")];
[self registerComponent:@"cell-slot" withClass:NSClassFromString(@"WXCellSlotComponent") withProperties: @{@"append":@"tree", @"isTemplate":@YES}];
// other non-default components should be checked with affine-base types.
[self _registerAffineTypes];
}
把所有默认的组件全部注册进去
分析div [self registerComponent:@"div" withClass:NSClassFromString(@"WXComponent") withProperties:nil];
+ (void)registerComponent:(NSString *)name withClass:(Class)clazz withProperties:(NSDictionary *)properties
{
if (!name || !clazz) {
return;
}
WXAssert(name && clazz, @"Fail to register the component, please check if the parameters are correct !");
//在工厂类里面 注册
[WXComponentFactory registerComponent:name withClass:clazz withPros:properties];
NSMutableDictionary *dict = [WXComponentFactory componentMethodMapsWithName:name];
dict[@"type"] = name;
if (properties) {
NSMutableDictionary *props = [properties mutableCopy];
if ([dict[@"methods"] count]) {
[props addEntriesFromDictionary:dict];
}
[[WXSDKManager bridgeMgr] registerComponents:@[props]];
} else {
[[WXSDKManager bridgeMgr] registerComponents:@[dict]];
}
}
工厂方法做了哪些?
[WXComponentFactory registerComponent:name withClass:clazz withPros:properties];
- (void)registerComponent:(NSString *)name withClass:(Class)clazz withPros:(NSDictionary *)pros
{
WXAssert(name && clazz, @"name or clazz must not be nil for registering component.");
WXComponentConfig *config = nil;
[_configLock lock];
config = [_componentConfigs objectForKey:name];
if(config){
WXLogInfo(@"Overrider component name:%@ class:%@, to name:%@ class:%@",
config.name, config.class, name, clazz);
}
config = [[WXComponentConfig alloc] initWithName:name class:NSStringFromClass(clazz) pros:pros];
//WXComponentConfig 只保存了pros
[_componentConfigs setValue:config forKey:name];
//存入到工厂方法中的字典中
[config registerMethods];
//通过while循环 将类里面所有的方法 分为两类 _syncMethods _asyncMethods 放到这个两个集合里面使用
[self registerAffineType:name withClass:clazz];
[_configLock unlock];
}
[config registerMethods]; 做了那些
- (void)registerMethods
{
Class currentClass = NSClassFromString(_clazz);
if (!currentClass) {
WXLogWarning(@"The module class [%@] doesn't exit!", _clazz);
return;
}
while (currentClass != [NSObject class]) {
unsigned int methodCount = 0;
Method *methodList = class_copyMethodList(object_getClass(currentClass), &methodCount);
for (unsigned int i = 0; i < methodCount; i++) {
NSString *selStr = [NSString stringWithCString:sel_getName(method_getName(methodList[i])) encoding:NSUTF8StringEncoding];
BOOL isSyncMethod = NO;
if ([selStr hasPrefix:@"wx_export_method_sync_"]) {
isSyncMethod = YES;
} else if ([selStr hasPrefix:@"wx_export_method_"]) {
isSyncMethod = NO;
} else {
continue;
}
NSString *name = nil, *method = nil;
SEL selector = NSSelectorFromString(selStr);
if ([currentClass respondsToSelector:selector]) {
method = ((NSString* (*)(id, SEL))[currentClass methodForSelector:selector])(currentClass, selector);
}
if (method.length <= 0) {
WXLogWarning(@"The module class [%@] doesn't has any method!", _clazz);
continue;
}
NSRange range = [method rangeOfString:@":"];
if (range.location != NSNotFound) {
name = [method substringToIndex:range.location];
} else {
name = method;
}
NSMutableDictionary *methods = isSyncMethod ? _syncMethods : _asyncMethods;
[methods setObject:method forKey:name];
}
free(methodList);
currentClass = class_getSuperclass(currentClass);
}
}
通过while循环 将类里面所有的方法 分为两类 _syncMethods _asyncMethods 放到这个两个集合里面使用
从渲染的方向来看
self.view.backgroundColor = [UIColor whiteColor];
_instance = [[WXSDKInstance alloc] init];
_instance.viewController = self;
_instance.frame = CGRectMake(0, 100, ScreenWidth, SCREEN_HEIGHT - 100);
__weak WeexViewController * weakSelf = self;
_instance.onCreate = ^(UIView *view) {
[weakSelf.weexView removeFromSuperview];
weakSelf.weexView = view;
[weakSelf.view addSubview:weakSelf.weexView];
};
NSDictionary *options = @{@"url":@"http://pic26.nipic.com/20121221/9252150_142515375000_2.jpg"};
//整个渲染的入口
[self.instance renderWithURL:[[NSBundle mainBundle]URLForResource:@"index" withExtension:@"js"] options:options data:nil];//他具体做了什么呢
[self.instance renderWithURL:[[NSBundle mainBundle]URLForResource:@"index" withExtension:@"js"] options:options data:nil]; 主要做了哪些
- (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data
{
if (!url) {
WXLogError(@"Url must be passed if you use renderWithURL");
return;
}
_scriptURL = url;
[self _checkPageName];
[self.apmInstance startRecord:self.instanceId];
self.apmInstance.isStartRender = YES;
self.needValidate = [[WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)] needValidate:url];
WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy];
* [self _renderWithRequest:request options:options data:data];//做请求*
NSURL* nsURL = [NSURL URLWithString:options[@"DATA_RENDER_JS"]];
[self _downloadAndExecScript:nsURL];
}
[self _renderWithRequest:request options:options data:data];//做请求*
- (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data;
{
/*
省略一坨代码
*/
//核心就是下载下来了js 去渲染
[strongSelf _renderWithMainBundleString:jsBundleString];
}
[strongSelf _renderWithMainBundleString:jsBundleString];
渲染的第一步
- (void)_renderWithMainBundleString:(NSString *)mainBundleString
{
/*
省略一坨代码
*/
//生成容器
WXPerformBlockOnMainThread(^{
_rootView = [[WXRootView alloc] initWithFrame:self.frame];
_rootView.instance = self;
if(self.onCreate) {
self.onCreate(_rootView);
}
});
// 确保全部注册
[WXSDKEngine registerDefaults];
//将数据交给 JS执行环境
[[WXSDKManager bridgeMgr] createInstance:self.instanceId template:mainBundleString options:dictionary data:_jsData];
}
- (void)createInstance:(NSString *)instanceIdString
template:(NSString *)jsBundleString
options:(NSDictionary *)options
data:(id)data
{
//获取JSFramwork 的上下文环境
[self callJSMethod:@"createInstanceContext" args:@[instanceIdString, newOptions, data?:@[]] onContext:nil completion:^(JSValue *instanceContextEnvironment) {
......
//执行index.js
[sdkInstance.instanceJavaScriptContext executeJavascript:jsBundleString];
.....
}
}
到此 为止 就是 原生与JS的通信
最初这句代码时 他的内部还执行了 注册JS调用原生的方法
[[WXSDKManager bridgeMgr] executeJsFramework:script];//执行JSFramwork
这些都是注册可调用的原生方法
/**
* Register callback when call __updateComponentData tasks occur. only use for data render
*/
- (void)registerCallUpdateComponentData:(WXJSCallUpdateComponentData)callUpdateComponentData;
/**
* Register callback when call native tasks occur
*/
- (void)registerCallNative:(WXJSCallNative)callNative;
/**
* Register callback when addElement tasks occur
*/
- (void)registerCallAddElement:(WXJSCallAddElement)callAddElement;
/**
* Register callback when createBody tasks occur
*/
- (void)registerCallCreateBody:(WXJSCallCreateBody)callCreateBody;
/**
* Register callback when removeElement tasks occur
*/
- (void)registerCallRemoveElement:(WXJSCallRemoveElement)callRemoveElement;
/**
* Register callback when removeElement tasks occur
*/
- (void)registerCallMoveElement:(WXJSCallMoveElement)callMoveElement;
/**
* Register callback when updateAttrs tasks occur
*/
- (void)registerCallUpdateAttrs:(WXJSCallUpdateAttrs)callUpdateAttrs;
/**
* Register callback when updateStyle tasks occur
*/
- (void)registerCallUpdateStyle:(WXJSCallUpdateStyle)callUpdateStyle;
/**
* Register callback when addEvent tasks occur
*/
- (void)registerCallAddEvent:(WXJSCallAddEvent)callAddEvent;
/**
* Register callback when removeEvent tasks occur
*/
- (void)registerCallRemoveEvent:(WXJSCallRemoveEvent)callRemoveEvent;
/**
* Register callback when createFinish tasks occur
*/
- (void)registerCallCreateFinish:(WXJSCallCreateFinish)callCreateFinish;
/**
* Register callback for global js function `callNativeModule`
*/
- (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock;
/**
* Register callback for global js function `callNativeComponent`
*/
- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock;
注册流程
- (void)registerCallCreateBody:(WXJSCallCreateBody)callCreateBody
{
//生明一个代码块 用来相应JS调用的方法
id WXJSCallCreateBodyBlock = ^(JSValue *instanceId, JSValue *body,JSValue *ifCallback) {
NSString *instanceIdString = [instanceId toString];
NSDictionary *bodyData = [body toDictionary];
WXLogDebug(@"callCreateBody...%@, %@,", instanceIdString, bodyData);
return [JSValue valueWithInt32:(int32_t)callCreateBody(instanceIdString, bodyData) inContext:[JSContext currentContext]];
};
//把方法注册给JS
_jsContext[@"callCreateBody"] = WXJSCallCreateBodyBlock;
}
处理回调回来的数据
[_jsBridge registerCallCreateBody:^NSInteger(NSString *instanceId, NSDictionary *bodyData) {
WXPerformBlockOnComponentThread(^{
[WXCoreBridge callCreateBody:instanceId data:bodyData];
});
return 0;
}];
[WXCoreBridge callCreateBody:instanceId data:bodyData];
对传回来的数据解析 得出 样式 事件
NSDictionary* styles = data[@"style"];
[self _parseStyleBeforehand:styles key:@"margin" render:render];
[self _parseStyleBeforehand:styles key:@"padding" render:render];
[self _parseStyleBeforehand:styles key:@"borderWidth" render:render];
[styles enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([key isEqualToString:@"margin"] || [key isEqualToString:@"padding"] || [key isEqualToString:@"borderWidth"]) {
return;
}
ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
render->AddStyle([key UTF8String], value);
}
});
}];
for (id obj in data[@"event"]) {
ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
render->AddEvent(value);
}
});
}
int childIndex = 0;
for (NSDictionary* obj in data[@"children"]) {
[self _parseRenderObject:obj parent:render index:childIndex ++ pageId:pageId];
}
+ (void)callMoveElement:(NSString*)pageId ref:(NSString*)ref parentRef:(NSString*)parentRef index:(int)index
{
WeexCore::WeexCoreManager::Instance()->script_bridge()->core_side()->MoveElement([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [parentRef UTF8String] ?: "", index);
}
+ (void)callUpdateAttrs:(NSString*)pageId ref:(NSString*)ref data:(NSDictionary*)data
{
WeexCore::RenderManager::GetInstance()->UpdateAttr([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [self _parseMapValuePairs:data]);
}
+ (void)callUpdateStyle:(NSString*)pageId ref:(NSString*)ref data:(NSDictionary*)data
{
WeexCore::RenderManager::GetInstance()->UpdateStyle([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [self _parseMapValuePairs:data]);
}
+ (void)callAddEvent:(NSString*)pageId ref:(NSString*)ref event:(NSString*)event
{
WeexCore::WeexCoreManager::Instance()->script_bridge()->core_side()->AddEvent([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [event UTF8String] ?: "");
}
+ (void)callRemoveEvent:(NSString*)pageId ref:(NSString*)ref event:(NSString*)event
{
WeexCore::WeexCoreManager::Instance()->script_bridge()->core_side()->RemoveEvent([pageId UTF8String] ?: "", [ref UTF8String] ?: "", [event UTF8String] ?: "");
}
+ (void)callUpdateFinish:(NSString*)pageId
{
WeexCore::WeexCoreManager::Instance()->script_bridge()->core_side()->UpdateFinish([pageId UTF8String] ?: "", nullptr, 0, nullptr, 0);
}
int IOSSide::UpdateFinish(const char* page_id, const char* task, int taskLen,
const char* callback, int callbackLen)
{
RenderPage *page = RenderManager::GetInstance()->GetPage(page_id);
if (page == nullptr) {
return -1;
}
NSString* ns_instanceId = NSSTRING(page_id);
//到这里开始给 空间开始处理
WXComponentManager* manager = [WXSDKManager instanceForID:ns_instanceId].componentManager;
if (!manager.isValid) {
return -1;
}
[manager startComponentTasks];
[manager updateFinish];
return 0;
}
总结一下