1

概要

  • iOS プロジェクトでUITableViewは、UITableView の行を移動しようとしています。
  • 私のモデルでは、データの順序が変更されているため、テーブルで視覚的に表示しようとしています。そのため、UITableViewの方法を使用しましたmoveRowAtIndexPath:toIndexPath:
  • そのためにNSIndexPath、UITableView のメソッドに渡すインスタンスを作成しました。

漏れが発生したとき

  • メソッドを使用して NSIndexPath インスタンスを作成しindexPathForRow: section:(コード セクションを参照)、それをUITableViewのメソッドmoveRowAtIndexPath: toIndexPath:に渡すと、リークが発生します。

ノート:

  • ARC(自動参照カウント)を使用しています
  • X コード 4.3.1
  • Instruments (Xcode メニュー - Product > Profile) を使用して、メモリ リークを特定しました。

コード: (UITableViewController 内)

NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:0]; //leaking

[self.tableView beginUpdates];
[self.tableView moveRowAtIndexPath:originalIndexPath toIndexPath:newIndexPath]; //I think this causes the leak
[self.tableView endUpdates];

私が試した手順

  • メソッドの呼び出しをコメント アウトするとmoveRowAtIndexPath:originalIndexPath toIndexPath:、メモリ リークが防止されます
  • 私は手動で使用CFReleaseしました(これが自動参照カウント環境での良い習慣であるかどうかはわかりません)

    CFRelease((__bridge void *)toIndexPath);

質問:

  • なぜこれが起こるのですか?それに対する解決策はありますか?
  • 計測器のメモリ リークの結果は正確ですか?
  • UITableView のメソッドにバグはありますmoveRowAtIndexPath:originalIndexPath toIndexPath:か?
  • CFRelease はオプションですか? CFRelease が既に解放されているメモリを解放しようとした場合にアプリがクラッシュするのを防ぐ安全な方法はありますか (上記の正確なコードを参照)。
4

2 に答える 2

1

投稿したコードによって、ARCセットアップでメモリリークが発生することはありません(また、ARCがない場合も同様です)。

実際にバグが疑われる場合(UITableViewがNSIndexPathオブジェクトの解放に失敗するなど)、一時的な回避策として手動で解放を試みることができます。しかし、アニメーションが完了した後、それがリリースされていないだけでよろしいですか?アニメーションがない場合でも、アイドルループに到達するまでindexPathオブジェクトが解放されない可能性があります(これはGUIコンポーネントで非常に一般的であり、明らかに自動解放されたオブジェクトでも同様です)。

ただし、それが実際にリークであることを確認するために、長期的にメモリが時間とともに増加するかどうかを調査してみてください(UITableViewが最新のindexPathオブジェクトに固執している可能性があり、おそらく問題にはなりません)。 。また、NSZombieEnabled環境変数を設定してデバッガーを実行してみてください。これにより、オブジェクトをダブルリリースしようとしたときに、デバッガーが検出されて侵入します。

于 2012-03-20T11:43:32.633 に答える
1

コメントを追加するのに十分な担当者がいないため、回答を追加する必要があります。この漏れも見ます。私は ARC を使用しておらず、beginUpdates/endUpdates を使用して moveRowAtIndexPath:toIndexPath への単一の呼び出しをラップしていません: このメソッドを呼び出すたびに、インスツルメントは NSIndexPath の 32 バイトのリークを主張します。

NSIndexPath の indexPathForRow:inSection: への呼び出しは、手動で解放する必要のない自動解放オブジェクトを返す必要があります。moveRowAtIndexPath:toIndexPath: がオブジェクトを誤って保持しているため、リークが発生していると思われます。

moveRowAtIndexPath:toIndexPath: の呼び出しの前後に NSIndexPath の保持カウントをログに記録するデバッグ コードを追加し、前に 1 を取得し (自動解放プールにあるため、これは予想されることです)、その後は 5 を取得しました (追加されていない限り、間違いなく予想されません)。自動解放プールにあと 4 回!)

編集: https://devforums.apple.com/message/639904も参照してください(Apple Developer アカウントが必要です)

于 2012-04-09T08:07:49.533 に答える