weex開發 - 載入index.js崩潰,白屏(may it has been destroyed so method:fireEvent is ignored,Url must be passe)
阿新 • • 發佈:2019-01-10
最近,博主在做weex專案中發現了一個奇怪的問題,分別會報如下幾個錯誤:
1.[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0] 2.<Weex>[info]WXBridgeContext.m:552, No send queue for instance:<WXSDKInstance: 0x7ff1645261d0; id = 0; rootView = (null); url= (null)>, may it has been destroyed so method:fireEvent is ignored 3.<Weex>[error]WXSDKInstance.m:149, Url must be passed if you use renderWithURL
博主載入index.js程式碼是這麼寫的:
//跳轉
WXDemoViewController *demo = [[WXDemoViewController alloc] init];
demo.url = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@/index.js",[NSBundle mainBundle].bundlePath]];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:demo];
[[UIApplication sharedApplication] delegate].window.rootViewController = nav;
//載入
NSURL *URL = [self testURL: [self.url absoluteString]];
NSString *randomURL = [NSString stringWithFormat:@"%@%@random=%d",URL.absoluteString, [email protected]"&":@"?",arc4random()];
[_instance renderWithURL:[NSURL URLWithString:randomURL] options:@{@"bundleUrl":randomURL} data:nil];
其中其他的初始化和配置博主就不一一貼出來了,不會的可以weex platform add ios來增加,weex run ios檢視,也可以在生成的工程中開啟target執行檢視。
以上和通過weex platform add ios生成的工程寫法一樣,但是卻莫名其妙白屏,現實url為空,博主又嘗試了將這樣寫:
[_instance renderWithURL:[NSURL URLWithString:self.url] options:@{@"bundleUrl":self.url.absoluteString} data:nil];
或
//urlStr是一個字串
demo.urlStr = [NSString stringWithFormat:@"file://%@/index.js",[NSBundle mainBundle].bundlePath];
[_instance renderWithURL:[NSURL URLWithString:urlStr] options:@{@"bundleUrl":urlStr} data:nil];
但是結果,經過[NSURL URLWithString:urlStr]之後的NSURL型別卻是空,前者顯示為空白,後者直接崩潰了,是不是很奇怪,博主經過斷點進入到WXSDKInstance.m中發現如下程式碼,可以知道罪魁禍首是url=nil導致的。但是明顯url不應該為空的,所以就很奇怪了。
//後者出現的問題
- (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data
{
if (!url) {
WXLogError(@"Url must be passed if you use renderWithURL");
return;
}
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];
[WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTNetworkHanding phase:WXTracingBegin functionName:@"renderWithURL" options:@{@"bundleUrl":url?[url absoluteString]:@"",@"threadName":WXTMainThread}];
}
在WXBridgeContext.m檔案中,也有著一段程式碼
//前者出現的問題
- (void)executeJsMethod:(WXCallJSMethod *)method
{
WXAssertBridgeThread();
if (!method.instance) {
WXLogError(@"Instance doesn't exist!");
return;
}
NSMutableArray *sendQueue = self.sendQueue[method.instance.instanceId];
//sendQueue莫名其妙變nil了,實在是找不到任何原因,一步步執行,也毫無頭緒
if (!sendQueue) {
WXLogInfo(@"No send queue for instance:%@, may it has been destroyed so method:%@ is ignored", method.instance, method.methodName);
return;
}
[sendQueue addObject:method];
[self performSelector:@selector(_sendQueueLoop) withObject:nil];
}
經過以上探索,發現似乎和instance和url有關,所以嘗試直接把url寫死在載入的地方:
NSString *bundleUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/index.js",[NSBundle mainBundle].bundlePath]].absoluteString;
[_instance renderWithURL:[NSURL URLWithString:bundleUrl] options:@{@"bundleUrl":bundleUrl} data:nil];
發現困擾了博主快兩天的問題就這麼解決了,最後的結論是沒有結論,猜測可能在初始化SDK的時候有個時間差,有些東西沒有初始化好,因為屬性傳值絕對不可能變nil的啊,也許目前這樣寫也只是一個權宜之計,但卻真正的解決了這個問題,在官方沒回復前就先這麼些吧,有結果再更新。
補充一下,還有一個坑造成這個問題的原因,你的url中有中文,需要進行轉碼:
[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];