2011-03-30 78 views
1

這是我在第一篇文章stackoverflow.com所以請善待(倒帶);)的Objective-C/iOS版:消息發送到釋放實例

我有,其目的是爲了顯示博客文章(導航基礎的應用標題)在表視圖(與JSON)。 我碰到的問題發生在一個單元離開屏幕然後回來時。 我得到了一個EXC_BAD_ACCESS(因爲我發送了一個消息給一個釋放的實例),所以我努力去理解它從哪裏來,我終於找到了解決方案。但事實是,我並不完全明白問題是如何發生的。這就是爲什麼我需要有人給我啓發,我認爲這是基本的理解!

當連接到JSON Web服務完成加載時,我解析JSON代碼以獲取博客文章列表(recentPosts),然後爲每篇文章(blogArticle)創建一個BlogArticle對象,將其存儲在MutableArray伊娃(allEntries),並插入到表視圖中的一行:

​​

這裏的BlogArticle對象的這竟然是問題的根源初始化:

- (id)initWithDictionary:(NSDictionary *)article 
{ 
    if (self = [super init]) 
    { 
     // title = [[[article valueForKey:@"title"] gtm_stringByUnescapingFromHTML] copy]; 
     // title = [[NSString alloc] initWithString:[[article valueForKey:@"title"] gtm_stringByUnescapingFromHTML]]; 
     title = [[article valueForKey:@"title"] gtm_stringByUnescapingFromHTML]; 
    } 

    return self; 
} 

所以每次的Objective-C編程誰也不像我這樣不討人喜歡告訴標題在分配之前從未被分配。如果我取消註釋上面兩行之一,它將起作用。程序崩潰什麼時候我嘗試初始化一個細胞與title變量,在這裏:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    NSLog(@"indexPath.row = %i", indexPath.row); 

    // Configure the cell. 
    BlogArticle *article = [allEntries objectAtIndex:indexPath.row]; 

    cell.textLabel.text = article.title; 

    return cell; 
} 

現在,我需要明白的是爲什麼它編譯/工作不分配伊娃並在它到底會造成麻煩(或者標題內容的確切位置被釋放,導致程序崩潰)。 關於iOS環境中的內存管理的任何好資源(noob友好)將不勝感激。

感謝提前:)

+1

無關你的問題,但是你似乎在'for'循環中泄漏了'blogArticle'Instances。 – 2011-03-30 13:44:37

+0

至於內存管理,Apple的[文檔](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043- BEHDEDDB)應該有你需要知道的一切。確保你真的瞭解「內存管理規則」部分。 – 2011-03-30 13:47:12

+0

「泄漏」是什麼意思?分配內存並永不釋放它? – teum 2011-03-30 15:42:47

回答

3

此行

title = [[article valueForKey:@"title"] gtm_stringByUnescapingFromHTML]; 

被分配一個自動釋放字符串。從本質上講,可以想象一下,自動釋放的字符串將在該方法結束時釋放(儘管它可以持續更長時間,以這種方式考慮它會很有用)。

你知道字符串會被自動釋放,因爲該方法gtm_stringByUnescapingFromHTML的名稱不與allocnewcopymutableCopy啓動。

您可以添加retain,中止它得到自動釋放:

title = [[[article valueForKey:@"title"] gtm_stringByUnescapingFromHTML] retain]; 

現在你自己的字符串,它不會釋放,直到你這麼說。

我知道的最好的總結是蘋果自己的文檔here

+0

好的,事實上,我想知道如何識別返回自動釋放對象的方法,謝謝你的提示! – teum 2011-03-30 16:24:02

1

那麼,問題是,你必須初始化你的對象,如果你想自己管理它的內存。你爲什麼要管理標題的記憶?

非常簡單: 每個對象引用,存儲在一個Array,Set,Dictionary等。由數組,字典和集管理。

如果您現在只是在您的單元格中使用此引用(通過書寫:「title = ...」),則還會將引用添加到單元格中。現在單元格也負責對象引用。所以如果tableView想釋放你的單元格,這會不時發生以節省內存,單元格會釋放你的標題對象。這會導致NSDitionary非常難過,因爲NSDictionary想要關心存儲在它自己內部的對象。

所以,你可以寫在的tableView-方法如下:

cell.textLabel.text = [article.title retain]; 

還是自己方法的註釋行。這意味着,你將「提升」你的對象的存儲級別,如果它被釋放,存儲級別本身將減少1。 如果存儲水平將達到零,它將被完全釋放(即應該發生,如果你的TableCell被釋放,你的NSDictionary)

我希望我可以幫助你有點:)

+0

感謝您的詳細解釋。 – teum 2011-03-30 16:46:31

相關問題