2011-12-28 53 views
0

這裏是我的代碼簡化:以一個對象了MutableArray的,並將其放置在一個新的對象

NSMutableArray* buildBlocks = [[[NSMutableArray alloc] initWithCapacity:0] retain]; 
Block* selectedBlock = [[[Block alloc] init] retain]; 

// Add several blocks to "buildBlocks" 

for(int i=0; i < [buildBlocks count]; i++) 
{ 
    Block* tempBlock = [buildBlocks objectAtIndex:i]; 

    if(tempBlock.selected) 
    { 
     // Move the block to the selected block 
     selectedBlock = tempBlock; 

     // Take the block out of the array 
     [buildBlocks removeObjectAtIndex:i]; 
    } 
} 

// Some code later 

if(selectedBlock.selected) // <---- Crashes here 
{ 
    // Do stuff 
} 

我要選擇的塊複製到「SelectedBlock,」刪除塊從數組中,然後再使用「SelectedBlock」。當我用這個代碼,我總是得到「EXC_BAD_ACCESS我覺得在程序釋放數據。‘SelectedBlock’它之前,我想我在做什麼錯

更新:?

感謝大家幫我解決它

+0

Xcode只是一個IDE。與這個問題無關。 – vikingosegundo 2011-12-28 22:57:19

+0

請注意,無條件前進('++ i'或'i ++')會導致您在刪除任何對象時跳過對象。只有在不移除物體的情況下才會提前進行。 – 2011-12-28 23:14:41

回答

0

我想說,當你從陣列中移除它時,塊會從你的下面釋放出來,但是你已經在裏面放入了虛假的(和不必要的)retains,所以很難告訴發生了什麼事,卻看不到你所遺漏的代碼。

通常情況下,當我從數組中刪除並反對並想要保留它時,我保留它。但是你仍然過度保留,所以可能不是問題,但沒有看到其餘的方法,我不能確定。

0

在這裏你去:

NSMutableArray* buildBlocks = [[[NSMutableArray alloc] initWithCapacity:0] retain]; 
Block* selectedBlock; 

// Add several blocks to "buildBlocks" 

for(int i=0; i < [buildBlocks count]; i++) 
{ 
    Block* tempBlock = [buildBlocks objectAtIndex:i]; 

    if(tempBlock.selected) 
    { 
     // Move the block to the selected block 
     selectedBlock = tempBlock; 
     [selectedBlock retain]; // Retain selectedBlock here 

     // Take the block out of the array 
     [buildBlocks removeObjectAtIndex:i]; 
    } 
} 

// Some code later 

if(selectedBlock.selected) // <---- Crashes here 
{ 
    // Do stuff 
} 

[selectedBlock release]; // release when done. 

基本上,你保留一個全新的,從未使用過塊在第2行selectedBlock從來沒有得到保留,當你從數組中刪除它,它被摧毀。因此,selectedBlock指向一個陳舊的舊內存導致崩潰。

+0

那麼,爲什麼提問者的代碼是錯誤的,爲什麼這個代碼更好? (另外,如果數組爲空,會發生什麼情況?) – 2011-12-28 23:13:45

+0

通常您會看到'selectedBlock = [tempBlock retain];',但上面寫成兩行,只是爲了清楚起見。 – amattn 2011-12-28 23:15:15

+0

理想情況下,您應該將selectedBlock初始化爲零。 'Block * selectedBlock = nil;' – 2011-12-29 05:50:15

5
Block* selectedBlock = [[[Block alloc] init] retain]; 

這將創建(和不必要的保留,因爲你已經擁有它)的新塊。爲什麼你想要創建一個新的,當你的目標是檢索一個你已經有的?

// Move the block to the selected block 
selectedBlock = tempBlock; 

這番話沒有任何意義。沒有什麼東西從一個塊移到另一個塊;你正在設置selectedBlock變量指向你從數組中獲得的塊。在那之後,selectedBlocktempBlock都指向同一個塊,它是數組中的塊。

// Take the block out of the array 
[buildBlocks removeObjectAtIndex:i]; 

陣列擁有它所包含的所有塊,所以當你刪除您從數組,數組釋放它得到了塊。如果這是該塊的唯一所有權,則該塊因此被解除分配。之後的任何使用都是無效的。

如...

if(selectedBlock.selected) // <---- Crashes here 

selectedBlock點,你有,然後從塊數組中刪除。假設數組是唯一擁有它的數據,那麼在這一點上它是一個死對象,所以是的,給它發送一條消息會導致崩潰。

您保留了初始化爲selectedBlock的對象,但未保留稍後用該對象替換該對象的對象。保留該初始對象不會主動保留您分配給該變量的未來對象;它只保留了最初的對象。

有您需要更改幾件事情:

  1. 初始化selectedBlocknil,不是指針到一個新的模塊。

  2. 不要隨意保留東西。始終保留一個目的。如果你不完全理解爲什麼保留某些東西是爲了做什麼(「讓它不崩潰」本身並不是一個可以接受的理由),那麼不要只是在它上面留下一個保留。瞭解the Advanced Memory Management Programming Guide中的內存管理規則,您將知道何時需要保留以及爲什麼您的retain不在[[[Block alloc] init] retain]中是不必要的。

  3. 當您保留某些內容時,請始終使用releaseautorelease消息將其與之平衡。你沒有平衡的保留是泄漏,最終泄漏會導致問題。在iOS下,從用戶的角度來看,它們會導致崩潰(更準確地說,您使用的內存太多,系統會殺死您的應用程序)。

  4. 當您將陣列中的對象分配到selectedBlock時,請保留它並自動釋放它,然後再將其從陣列中移除。保留讓你成爲一個擁有者,autorelease使這個臨時變爲現實;作爲一個所有者,只要持續這個時間,就會使對象活得足夠長,以便你使用它,從而防止崩潰。

  5. 不要打擾詢問所選塊是否被選中。如果選擇了塊,則只指定一個塊的指針selectedBlock,因此在您使用selectedBlock時,您已經知道它已被選中。結合上面的#1,您可以簡單地測試selectedBlock是否爲nil;如果它不是nil,則有一個選定的塊,如果它是nil,則沒有找到(即沒有)選定的塊。

  6. 當您得到此代碼工作後,將其轉換爲ARC。 (在Edit/Refactor菜單中有一個菜單項。)然後,您不必保留或釋放或自動釋放任何東西;大多數事情都行得通。

相關問題