2011-09-20 231 views
0

我使用Master/Detail模板和ARC在Xcode 4.3測試版下構建了一個應用程序,然後發現我無法提交它,所以將它移回到Xcode 4.2,添加了所有內存管理。 這不是泄漏,但每次我從主顯示屏訪問詳細記錄時,Profiler所說的情況都在增長 - 每次都有一個詳細控制器。什麼是持有我的控制器?

我已經聲明瞭控制器的主(根)控制器伊娃和屬性(在.m文件synthasized):

@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> { 
... 
    @private 
    DetailViewController *detailViewController; 
} 
... 
@property (nonatomic, retain) DetailViewController *detailViewController; 
@end 

... 
@synthasize detailViewController; 

新實例上的主列表項的選擇創建在-tableView:didSelectRowAtIndexPath方法調用(的NSLog的加入表明漸進保留計數):

tableView:didselectRowAtIndexPath call (NSLog's added to show progressive retain count): 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"1 dvc %i",[self.detailViewController retainCount]); 
    self.detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; 
    NSLog(@"2 dvc %i",[self.detailViewController retainCount]); 
    NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
    detailViewController.detailItem = selectedObject;  
    [self.navigationController pushViewController:self.detailViewController animated:YES]; 
    NSLog(@"3 dvc %i",[self.detailViewController retainCount]); 
    [self.detailViewController release]; 
    NSLog(@"4 dvc %i",[self.detailViewController retainCount]); 
} 

爲了我的思維方式,這應該有正確的管理對象的生命週期和檢查,我把其他的NSLog在RootViewController的 - viewWillAppear方法來看看每次根(主)視圖出現時,保留計數。調試日誌顯示如下:

2011-09-20 15:17:34.402 ABRA[13133:207] RootViewController viewDidAppear DVC=0 
2011-09-20 15:17:38.410 ABRA[13133:207] 1 dvc 0 
2011-09-20 15:17:38.411 ABRA[13133:207] 2 dvc 2 
2011-09-20 15:17:38.467 ABRA[13133:207] 3 dvc 9 
2011-09-20 15:17:38.468 ABRA[13133:207] 4 dvc 8 
2011-09-20 15:17:41.889 ABRA[13133:207] RootViewController viewDidAppear DVC=3 
2011-09-20 15:17:45.137 ABRA[13133:207] 1 dvc 2 
2011-09-20 15:17:45.138 ABRA[13133:207] 2 dvc 2 
2011-09-20 15:17:45.330 ABRA[13133:207] 3 dvc 8 
2011-09-20 15:17:45.330 ABRA[13133:207] 4 dvc 7 

第一個是好的。該應用程序剛剛啓動,因此detailViewController保留計數爲零,因爲這是第一次進入tableView方法。

撥出後,計數是2(我以爲它應該是1)!

pushViewController將其顛倒爲9,然後我在放棄所有權的方法結束時釋放(計數8)。

當控制器被「彈出」(通過按下左導航欄按鈕)並且Root vew再次顯示後,計數仍然是3(一個用於getter/setter,顯然還有兩個其他東西仍然持有對它的引用)。

因此,當通過setter創建並應用另一個新實例時,舊對象的計數仍然是2,因此即使它通過合成設置器被新實例替換,它也會保留。

進一步迭代迴應「2,2,8,7,3」結果無限。儀器不會將此視爲泄漏,但我確實這樣做是因爲足跡越來越大!

爲什麼-alloc/-initWithNib導致保留計數爲2而不是1? 爲什麼推動第一次和第六次增加保留計數7? 我應該怎樣才能找到應該被釋放的東西?

+0

'retainCount'不會告訴你傑克。無用的方法。別叫它。如果您想追蹤泄漏情況,請使用分配工具,更具體地說,使用Heapshot分析。泄漏工具*可能*有幫助,但可能不會。 – bbum

回答

0

爲什麼-alloc/-initWithNib導致保留計數爲2,而 不是1?爲什麼推動增加保留計數7第一次 和6隨後?我應該如何發現 應該被釋放的時候是什麼?

@property(nonatomic,retain)DetailViewController * detailViewController;

這應該回答你的答案的一部分。你的財產也保留你的視圖控制器。解決這個問題,看看你的情況是否有所改善。(不要打擾把它放在屬性中,只是初始化一個局部變量並在方法結束時釋放,NavigationController會爲你保留viewController)

很難回答你的問題的第二部分,因爲我們不知道detailViewController上的detailItem屬性會發生什麼情況。只需修復上面的問題,然後編輯你的答案並取得進展。

0

我發現retainCount對於調試泄漏通常是不可靠的。

你試過這種變化:(基本上做的是DVC的延遲加載?)

tableView:didselectRowAtIndexPath call (NSLog's added to show progressive retain count): 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"1 dvc %i",[self.detailViewController retainCount]); 
    if (!self.detailViewController) { 
     self.detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; 
     NSLog(@"2 dvc %i",[self.detailViewController retainCount]); 
    } 
    NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
    detailViewController.detailItem = selectedObject;  
    [self.navigationController pushViewController:self.detailViewController animated:YES]; 
    NSLog(@"3 dvc %i",[self.detailViewController retainCount]); 
    // release dVC in your dealloc 
    // [self.detailViewController release]; 
    // NSLog(@"4 dvc %i",[self.detailViewController retainCount]); 

} 

更重要的是,你的DVC爲什麼不使用一個IBOutlet?

+0

用盡想法,如此重構沿着這些線(Plan C - 一個DetailViewController在數據集更改時被保留並重新配置)。等待ARC去黃金可能是最好的解決方案,但時間不利於我。 – RonC

+0

我很少使用initWithNibName,而是使用IBOutlets使其更容易。 – mahboudz

+0

self.detailViewController = [[DetailViewController alloc] initWithNibName:@「DetailViewController」bundle:nil]; 計爲兩個保留。一次因爲alloc/init和一次爲setter self.detailViewController做了保留。 – mahboudz