1. 程式人生 > >weex開發 - 載入index.js崩潰,白屏(may it has been destroyed so method:fireEvent is ignored,Url must be passe)

weex開發 - 載入index.js崩潰,白屏(may it has been destroyed so method:fireEvent is ignored,Url must be passe)

最近,博主在做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];