編集状態のUItableViewでデータの移動を実装するときにミスった。


UITableViewを編集状態にしてデータを移動すると以下のメソッドが呼ばれます。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath

このメソッド内でデータを実際に移動するのですがオブジェクトを型宣言で参照してたために嵌った。つまりオブジェクトについて忘れてたことがあるのでメモしておく。

以下のように実装してたらBadAccess発生。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{

    CCMCommentModel *tempComment =(CCMCommentModel*)[_chat.chatArray objectAtIndex:fromIndexPath.row];
    [_chat.chatArray removeObjectAtIndex:fromIndexPath.row];
    [_chat.chatArray insertObject:tempComment atIndex:toIndexPath.row];
}

色々やった挙句に気づいた。型宣言したもので参照しているので実体は配列に入っていたものを示している。リムーブメソッドが呼ばれてデータが破棄されて実体がなくなる。実体は無くともインサートメソッドでデータをチェックしていないのでそのまま追加される。もう一度このオブジェクトにアクセスするとBadAccessがでる。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{

    CCMCommentModel *tempComment =(CCMCommentModel*)[_chat.chatArray objectAtIndex:fromIndexPath.row];
    [tempComment retain];
    NSLog(@"リムーブ前retainCount=%d",[tempComment retainCount]);
    [_chat.chatArray removeObjectAtIndex:fromIndexPath.row];
    NSLog(@"リムーブ後retainCount=%d",[tempComment retainCount]);
    [_chat.chatArray insertObject:tempComment atIndex:toIndexPath.row];
    NSLog(@"インサート後retainCount=%d",[tempComment retainCount]);
   [tempComment release];
}

上のように書きなおしてNSLogでチェックしてみる。

リムーブ前retainCount=2
リムーブ後retainCount=1
インサート後retainCount=2

元々配列から参照されているのでリテインカウントは1。型から参照されてリテインカウントは2。配列からリムーブされるときにリリースされるのでリテインカントは1に、配列にインサートされるときに配列からリテインされてカウントは2。型からの参照を外せばリテインカウントは1に落ちます。

オブジェクトの扱い方を間違えるとこうなります。ARCならこういったことはおこらないのかな。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です