2012-04-21 38 views
1

我已經使用塊和ARC,並發現在某些情況下,iOS只在發佈版本崩潰。編寫代碼是錯誤的方式,就像這樣。iOS 5塊只與發佈版本崩潰

-(IBAction)clickedButtonA:(UIBarButtonItem*)sender event:(UIEvent*)event { 
    NSMutableArray *arrRows = [NSMutableArray arrayWithCapacity:0]; 
    #warning this code only crash on Release Build.... Don't use this 
    NSMutableDictionary * dicRow = [NSMutableDictionary dictionaryWithCapacity:0]; 
    [arrRows addObject:dicRow]; 
    dispatch_block_t block = ^{ 
    NSString *str = [NSString stringWithFormat:@"%@",[_tweet valueForKey:@"text"]]; 
    [[UIPasteboard generalPasteboard] setString:str]; 
    }; 
    [dicRow setValue:block forKey:kDicKeyLinkPopBlock]; 

    NSMutableArray *sections = [NSMutableArray arrayWithObject:arrRows]; 
    TOVLinkPopoverViewController *controller= [[TOVLinkPopoverViewController alloc] init]; 
    controller.arrayLink = sections; 
} 

而從其他控制器,當我訪問該塊時,它只會崩潰,我在發佈版本。我知道你需要複製塊

[dicRow setValue:[block copy] forKey:kDicKeyLinkPopBlock]; 

對於非塊感知類如NSMutableDictionary。

問題是「爲什麼它只在發佈版本上崩潰?」我知道這個「應該會崩潰」,這是使用block的錯誤方式,但是希望它在Debug版本上崩潰,所以我們可以在早期找到這種錯誤。

還有一個問題是「是否有任何構建設置使得此代碼隨調試構建崩潰?」

您可以從GitHub運行示例代碼, https://github.com/tomohisa/iOS_PopoverMenu_Notification

見ViewController.m並找到註釋掉的代碼(僅在崩潰釋放)。

+0

爲什麼初始化字典到容量0?然後嘗試添加一些內容? – utahwithak 2012-04-21 22:30:26

+0

@cwieldand [NSMutableDictionary dictionaryWithCapacity:0]和[[NSMutableDictionary alloc] init]一樣,我只是更喜歡使用它,因爲它很容易輸入。它是'可變的'dic,並加入到最後是沒有問題的。 – 2012-04-22 00:21:35

回答

6

你是對的,你需要添加[block copy]。這是因爲該塊是在當前棧幀中創建的(即在clickedButtonA:event:之內),但是隨後將其添加到字典中,並推測稍後將其拔出。當你稍後將它拉出來並使用它時,原來的堆棧框架已經消失,並且你將有一個指向一些隨機存儲器的指針,這些隨機存儲器可能不會(很可能不會)實際上成爲該塊。

當你複製塊時,如果它現在在堆棧上,那麼它會被複制到堆中,如果它已經在堆上,它就會保留它。這意味着你現在有一個可以在上下文之間傳遞的塊並且是有效的。

只有在發佈模式下才看到它崩潰的原因是因爲發佈模式將啓用編譯器優化,這完全改變了堆棧的處理方式。可能你在調試模式中非常幸運,不會看到問題,而只是你的應用程序設計的一個怪癖。