2011-12-28 9 views
0

ここでは簡略化され、私のコードは次のとおりです。MutableArrayの外にオブジェクトを取り、新しいオブジェクトに配置

私は「SelectedBlockは、」配列のうちのブロックを削除するには、選択されたブロックをコピーしたい
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は私が感じる 『私がそれをする前に、私はいつも何が私が間違っているの』取得

UPDATE:?

ありがとう

+0

Xcodeは単なるIDEです。この質問には関係ありません。 – vikingosegundo

+0

無条件に前進している( '++ i'または' i ++')は、あなたが何かを削除するとオブジェクトをスキップすることになります。オブジェクトを削除しない場合にのみ進むことができます。 –

答えて

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

質問者のコードが間違っているのはなぜですか?このコードはなぜ優れていますか? (配列が空の場合はどうなりますか?) –

+0

通常、 'selectedBlock = [tempBlock retain];'が表示されますが、上記は2つの行に分かれています。 – amattn

+0

selectedBlockを理想的にはnilに初期化する必要があります。 'Block * selectedBlock = nil;' –

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ポイントがarrayからを削除しました。配列がそれを所有する唯一のものだと仮定すると、この点では死んだオブジェクトなので、メッセージを送信するとクラッシュします。

selectedBlockで初期化したオブジェクトは保持しましたが、そのオブジェクトを後で置き換えたオブジェクトは保持しませんでした。その初期オブジェクトを保持しておけば、その変数に割り当てた将来のオブジェクトを事前に積極的に保持することはできませんでした。最初のオブジェクトだけを保持していました。

  1. 初期selectedBlocknilに、ではない、新たなブロックへのポインタ:

    は、変更する必要がいくつかあります。

  2. 物事を無作為に保持しないでください。常に目的を持ってください。あなたが何かを保持する理由が完全に理解できない場合は、のことです( "それはクラッシュしません"それだけでは受け入れられる理由ではありません)。 the Advanced Memory Management Programming Guideのメモリ管理ルールを理解すれば、いつ保持する必要があるのか​​、の[[[Block alloc] init] retain]が不要なことがわかります。

  3. 何かを保持している場合は、必ずreleaseまたはautoreleaseというメッセージで調整してください。あなたがバランスを保ちません保持は、リークであり、リークは最終的に問題を引き起こします。 iOSの下では、ユーザの視点からクラッシュを効果的に引き起こします(より正確には、メモリを使いすぎてシステムがアプリを殺す)。

  4. アレイのオブジェクトをselectedBlockに割り当てるときは、配列からオブジェクトを削除する前に保持しておいてください。保持はあなたを所有者にし、自動解放はそれを一時的にします。その所有物が所有者である限り、それが続く限り、オブジェクトを使用してクラッシュを防ぐのに十分長い間オブジェクトを生かしておくでしょう。

  5. 選択したブロックに選択したかどうか尋ねないでください。ブロックのポインタがselectedBlockに選択されている場合にのみ割り当てます。したがって、selectedBlockを使用するときまでに、そのポインタが選択されていることがわかります。上記の#1と組み合わせて、selectedBlocknilであるかどうかを簡単にテストできます。 nilではない場合、選択されたブロックがあり、nilであれば、選択されたブロックが見つかりませんでした(つまり、存在しません)。

  6. このコードが機能したら、それをARCに変換します。 (Edit/Refactorメニューにはこのためのメニュー項目があります。)次に、何も保持したり解放したりする必要はありません。ほとんどのものはうまく動作します。

関連する問題