2011-06-30 162 views
4

我已經投入了數天的時間來試圖弄清楚發生了什麼事情,並且對於我的生活我看不到我做錯了什麼。當用戶觸摸屏幕上的一個點時,我彈出一個UIPopover。彈出窗口有一個選項卡控制器和表格視圖,顯示關於該點的信息。但是,當酥料餅被駁回,它崩潰聲稱: - [UIAnimator removeAnimationsForTarget:]:消息發送到釋放實例UIPopoverController中的內存崩潰

這裏被加載視圖控制器代碼:

MyViewController *popView = [[MyViewController alloc] init]; 
myPop = [[UIPopoverController alloc] initWithContentViewController:pop]; 
[popView release]; 
myPop.delegate = self; 
[airportPop setPopoverContentSize:popView.view.frame.size]; 
[airportPop presentPopoverFromRect:CGRectMake(location.x,location.y,1,1) inView:self.mainView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 

- (void)dismissPopover { 
    if(myPop != nil) { 
     [myPop dismissPopoverAnimated:YES]; 
     [myPop.delegate popoverControllerDidDismissPopover:airportPop]; 
    } 
} 

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { 
    [myPop release]; 
    myPop = nil; 
} 

實際MyViewController是隻是一個UIViewController與(刪節爲了簡潔)初始化:

- (id)init 
{ 
    self = [super init]; 
    //create a newview 
    self.view = popView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, POPUP_WIDTH, POPUP_HEIGHT)]; 
    [popView release]; 

    topBar = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, POPUP_WIDTH, 30)]; 
      .... 
    [popView addSubview:topBar]; 
    [topBar release]; 

    //create a table view 
    self.table = [[UITableView alloc] initWithFrame:CGRectMake(0, 30, POPUP_WIDTH, POPUP_HEIGHT-30-49)]; 
     table.delegate = table.dataSource = self; 
     .... 

    //create a tab bar 
    tabBar = [[UITabBar alloc] initWithFrame:CGRectMake(0, POPUP_HEIGHT-49, POPUP_WIDTH, 49)]; 
    tabBar.delegate = self; 

    [popView addSubview:tabBar]; 
    [popView addSubview:table]; 

    [tabBar release]; 
    [table release]; 
    return(self); 
} 

dealloc的無非是[超級的dealloc]因爲一切基本上是由視圖擁有和視圖控制器會照顧Ø多f it。當myPop發佈時,在DidDismissPopover中,視圖也被釋放,所以這似乎工作正常。但不久之後,我發生了這起事故。

當彈出窗口關閉時,我是否需要做一些特殊的操作來放棄標籤視圖或表格視圖?

我在表中的單元格上使用autorelease,我應該停止這樣做嗎?

 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 

預先感謝您的幫助!任何想法都非常感謝!

-Kevin

+0

什麼是'popView'? –

回答

4

[myPop dismissPopoverAnimated:YES]將繼續訪問你的對象,不管方法調用之後,因爲你的動畫設定YES(有一個計時器和其他的東西去引擎蓋下執行該動畫)

所以,與其立即釋放該對象,您可以將其標記爲autorelease以推遲此操作,這實際上可能會解決該問題。

或者推遲釋放到一定時間後,確保動畫完成。你可以使用GCD(如果你使用的是iOS 4+),並且作爲UIKit中動畫的默認時間是0.3秒,下面的代碼應該可以做到。

double delayInSeconds = 0.3; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [myPop.delegate popoverControllerDidDismissPopover:airportPop]; 
}); 

編輯:你應該使用這個時間只爲測試建議,因爲它是遠遠沒有正確的方式來釋放一個對象。

您應該存儲一個指向UIPopover的指針,並將其釋放到您的類dealloc方法中。

+0

是的 - 這就是它......設置Animated爲NO似乎完全解決了崩潰問題。 (使用autorelease沒有。)所以,這是有道理的,但是如何知道什麼時候釋放popover? –

+0

順便說一句,0.3秒沒有工作..我繼續前進,並將其設置爲5,並沒有墜毀,因爲。 –

3
按照侑Exectables信息 - >參數鍵標籤 - >環境變量

NSZombieEnabled = YES 

CFZombie = 5 

MallocStackLoggingNoCompact = 1 

然後當你崩潰,你會自動獲得一個消息 這樣

一些事情

添加

(gdb)continue

2011-06-09 11:46:08.404測試[6842:4 0B] * - [_ NSArrayI 發佈]:發送到釋放實例0X64a4900

然後鍵入

(GDB)信息的malloc歷史0x64a4900

它會給你一個完整的歷史信息。

可能是它可以幫助你找到的地方。

還可以在碰撞時使用where命令。

+0

這就是我知道它在UIAnimator中的原因。每次調用的「發佈的類」都會有所不同,但通常會在崩潰時嘗試訪問表或Tab視圖。 –

+0

順便說一下,不知道CFZombie - 也會試試這個... –

+0

有沒有一種方法可以在lldb中使用這個調試工具? – atreat

0

避免等待動畫結束,最快的方式就是儘快建立popoverController.delegate = nil爲您關閉彈出窗口或酥料餅的委託方法

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 

被調用。

+1

這不適用於編程式關閉popovers。從蘋果方面來說,這是非常愚蠢的,不提供一個完整的回調或呼叫「didDismissPopover」呼叫。 – BastiBen