開篇
年后換工作開始接手Weex,開貼記錄下Weex相關的知識。本篇文章主要介紹一下WeexSDK在原生項目中大致的加載順序,從項目的啟動到界面渲染結束所走的主要流程。后續會放上項目中遇到的更多問題。
項目的啟動順序
AppDelegate 在
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中設置入口頁
比如:ActiveViewController
在ActiveViewController中 根據APP是否初次安裝,判斷安裝引導頁、啟動頁
啟動頁結束后 啟動WeexSDK
[WeexSDKManager setup];
之后根據是否有手勢密碼和登陸狀態判斷是否顯示密碼驗證頁面。
WeexSDKManager 啟動頁面的設置
初始化WeexSDK handler、module、componet組件的注冊。(在這里暴露自己封裝的相關的=module、componet組件名稱供Weex調用)
項目入口WXRootViewController
根據自己的調試需要設置.js文件的加載路徑,然后傳入加載需要的url進入設置的Controller,在這里進行頁面的適配,url的渲染進行加載拿到的url,以此為真正的入口進入到WeexSDK源碼中。
[[UIApplication sharedApplication] delegate].window.rootViewController = [[WXRootViewController alloc] initWithRootViewController:demo];
設置WXRootViewController 在WXRootViewController加載url時設置
- (id)initWithSourceURL:(NSURL *)sourceURL
{
WXBaseViewController *baseViewController = [[WXBaseViewController alloc]initWithSourceURL:sourceURL];
return [super initWithRootViewController:baseViewController];
}
WXBaseViewController
作為BaseViewController 每次頁面渲染都會進入到當前頁面,我們在頁面中設置iPhone X的適配等,并且根據不同的需要手動對特定的頁面進行刷新渲染(舉例:以通知的形式刷新頁面,或者根據某個.js文件的名稱對刷新操作做處理)。
并由此對 進行 _instance = [[WXSDKInstance alloc] init];進入具體的網址渲染操作。
WXSDKInstance 加載與源碼修改設置
WXSDKInstance的加載與設置主要通過下列三個方法進行,拿到的url進行加載然后對url根據我們不同的需要進行設置,渲染成功之后,根據需要添加我們需要的操作
- (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data;
- (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data{
/******* 這里進行加載方式的路徑切換 ******/
// //如果加載的是本地包
// NSURL *url;
// if ([request.URL.absoluteString containsString:[NSBundle mainBundle].bundlePath]) {
// url = request.URL;
// }else{
// url = [NSURL URLWithString:[self fileWithString:request.URL.absoluteString]];
// }
// request.URL = url;
//如果加載的是線上的
NSURL *url = request.URL;
...
}
- (void)_renderWithMainBundleString:(NSString *)mainBundleString{
...
[WXSDKEngine registerDefaults];
[[NSNotificationCenter defaultCenter] postNotificationName:WX_SDKINSTANCE_WILL_RENDER object:self];//渲染即將完成的標識
....
//需要在加載完成之后進行個人操作
....
}
至于 自定義 module與Component 擴展 官方給了詳細的介紹
項目中的問題:
1.APP殺死軟件收到url形式的通知,點擊無法打開對應的網址
收到推送消息之后以通知的形式發送給Weex前端,來用來控制頁面的跳轉。
省略代碼...
if (userInfo[@"url"]) {
NSDictionary * item = @{
@"param":userInfo
};
[[NSNotificationCenter defaultCenter] postNotificationName:@"push_moudle" object:self userInfo:item];
}
當軟件是啟動狀態是,收到推送發送通知,頁面正常跳轉,APP殺死的情況下,由于打開APP直接走AppDelegate中的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
進行發送通知,此時WeexSDK尚未啟動成功,所以Weex尚未注冊通知成功,無法進行對應的跳轉。
解決方案:在WXSDKInstance渲染加載結束之后,做2-3秒的延遲,拿到收到的遠程推送發送推送消息,此時WeexSDK已啟動成功收到推送消息
2.由Weex頁面進入到H5頁面或原生界面,返回之后Weex頁面不刷新
在WXBaseViewController中進行設置根據不同的需求設置方式大致分為兩種
- 在生命周期將要出現的時候判斷如果包含某個特定的.js文件對當前頁面進行刷新
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if ([self.navigationController isKindOfClass:[WXRootViewController class]]) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
if ([_sourceURL.absoluteString containsString:@"myWeb.js"]) {
[self _renderWithURL:_sourceURL];
}
}
- 通知方式刷新界面,收到通知重新渲染界面調用如下方法
[self _renderWithURL:_sourceURL];
3.線上打包與本地打包
線上打包:包括測試環境下的本地起服務加載與正式的線上加載,主要特點是不依賴本地的Views文件,實現熱更新,加載的內容由線上網址返回的.js文件決定。主要入口是本地bundlejs文件下的index.js文件。頁面的顯示的前提是必須有線上服務或者有本地服務在運行。
在WXSDKInstance中
- (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data;
//直接渲染網絡url
request.URL = url;
.....
}
本地打包:不依賴于線上的網址,將項目中用到的.js文件所在的Views文件夾放到項目中,對文件的加載路徑進行處理,直接由index.js作為入口訪問,本地Views文件夾下的.js文件實現頁面的加載。不需要起本地服務于線上服務的運行。
在WXSDKInstance中
- (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data;
方法中
//如果加載的是本地包
NSURL *url;
if ([request.URL.absoluteString containsString:[NSBundle mainBundle].bundlePath]) {
url = request.URL;
}else{
url = [NSURL URLWithString:[self fileWithString:request.URL.absoluteString]];
}
request.URL = url;
.....
}
//路徑處理
-(NSString*)fileWithString:(NSString*)str{
str = [str componentsSeparatedByString:@"?"].firstObject;
NSString* string = [NSString stringWithFormat:@"file://%@%@",[NSBundle mainBundle].bundlePath,str];
if ([string containsString:@"dist/"]) {
string = [string stringByReplacingOccurrencesOfString:@"dist" withString:@"bundlejs"];
}
return string;
}
后記
Weex一定程度上減少了原生的開發工作量,但是也有許多需要與原生交互的東西,作為第一篇記錄一下,以后有時間持續更新,希望分享更多Weex相關的內容。