iOS 6 でアプリをコンパイルし始めてから (そして iOS 7 から)、このメッセージが表示されるようになりました。iOS 6 では UITableViews がセルを管理する方法が異なることはわかっていますが、コードを変更する必要はありませんでした。しかし、このメッセージは、私がまだ見ていない潜在的な問題を示しているのではないかと心配しています。誰でも光を当てることができますか?
14 に答える
このエラーは、iOS 7 ベータ 5 以降 (iOS 7 GM/Release ビルドを含む) からログに表示されるようになりましたが、iOS 6 またはそれ以前の iOS 7 ベータのアプリでは発生したことはありませんでした。多くの実験の後、私は原因を見つけました:
UITableViewCell
セクション ヘッダー ビューにオブジェクトを使用し、 tableView:viewForHeaderInSection:
. これは、特に iOS 5 以降、Interface Builder を使用して StoryBoard のプロトタイプ テーブル ビュー セルとしてセクション ヘッダー ビューを簡単に設計できるようになったときから、一般的な方法のようです。
セクション ヘッダー ビューに通常のサブクラスのみを使用するようにアプリを変更するUIView
と、エラーがなくなり、さらに重要なことに、テーブル ビューでセクション ヘッダーがランダムに削除されなくなりました。
(iOS 7 ベータ 5 以降)ビュー階層内のすべてのオブジェクトとそれぞれのインデックス パスUITableView
のマッピングを内部的に維持しているように見えます。UITableViewCell
セクション ヘッダー (またはフッターのテーブル ビュー ヘッダー) にはインデックス パスがないため、これらのビューにオブジェクトを使用すると、インデックス パスがない をUITableViewCell
見つけるとテーブル ビューが混乱します。 UITableViewCell
、「再利用されているテーブルセルのインデックスパスがありません」というエラーが発生し、運が悪い場合は、テーブルビューに不具合が表示されます。
更新: Apple Dev Forums にアクセスできる場合は、それに関するスレッドを次に示します (私が開始しました): https://devforums.apple.com/message/882042#882042
そのスレッドで示唆されているように、あまりリファクタリングしたくない場合は、UIView
ラッパーを作成しUITableViewCell
て、それをセクション ヘッダー ビューとして返すことができます。
UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
[view addSubview:cell];
return view;
ただし、この「ラッパー」UIView
アプローチは AutoLayout とデバイスの回転ではうまく機能しないことに注意してください。そのため、回答の主要部分で説明されているサブクラスUIView
ではなく、ヘッダーとフッターのセルにサブクラスを使用することをお勧めします。UITableViewCell
ラッパーを作成する代わりに、UITableViewCell の contentView を返します。ストーリーボードで制約ジャブルを修正することを念頭に置いて
return cell.contentView;
私は同じ問題を抱えていて、問題を突き止めるのに数時間かかりました. [textField becomeFirstResponder]
セルの設定中に呼び出していたことがわかりました (ここでは、textField はカスタム tableviewcell の一部でした)。[textField becomeFirstResponder]
次に、keyboardWillShow 通知を投稿します。これにより、テーブルビューが途中で読み込まれ、悪名高い「再利用されているテーブル セルのインデックス パスがありません」というメッセージが表示されます。その呼び出しを削除すると、問題はなくなりました。
受け入れられた回答 (mluisbrown) に加えて、ヘッダー セルに autoresizingMask を追加する必要がありました。
UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
cell.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[view addSubview:cell];
return view;
これは UIKit の内部バグです - Apple 自身の開発フォーラムで言及されています。xcode の新しいバージョンでは修正されていると思われますが、これを修正するバージョンに関する情報は見つかりませんでした。
以前の投稿 (これは明らかに UIKit のバグであると述べました) への追加として、特定のケース (メッセージがテーブル上の奇妙な視覚化の不具合に関連していた) の回避策を見つけることができました。
どうやらカスタム セルのオーバーライド-(void)setEditing:animated:
が返るのに時間がかかりすぎていたようです。
私の以前のコードは次のとおりです。
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self someAdditionalCode];
}
次のように変更することで修正できました。
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
// DRM: we want to perform the actions from this block in the main thread, but
// asynchronously to avoid excessive delays which were causing issues.
//
dispatch_async(dispatch_get_main_queue(), ^void()
{
[self someAdditionalCode];
});
}
エラーメッセージが表示されるという同じ問題がありました。私が見る限り、デリゲートプロトコルの一部としてテキストフィールドによって呼び出された関数からテーブルビューをリロードすることによって引き起こされます。つまり、textFieldDidEndEditing -> [controller.tableview reload...]
これは明らかに古い質問ですが、iOS 8 以降でこの問題が引き続き発生するすべての人に役立つことを願っています。
カスタムUITableViewCell内にあるUIImageViewに画像を非同期ダウンロードするためにPINRemoteImageを使用していました。
画像がロードされたら、行のサイズを適切に変更するために(自動レイアウトを使用して動的な高さのセル)、次のように呼び出しました。
self.tableView beginUpdates;
self.tableView endUpdates;
その後、「再利用されているテーブル セルのインデックス パスがありません」というメッセージが表示され、アプリがクラッシュしていました。PINRemoteImageManagerResult ブロックがメイン スレッドにあると思っていましたが、そうではないことが判明しました。したがって、メイン スレッドで開始/終了の更新が呼び出されるようにすることで、問題が修正されました。
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.tableView beginUpdates];
[self.tableView endUpdates];
});
記録として、iOS 6 で実行しているときにもこのメッセージが表示されました。継承またはインポートされた一部のコードには、次のようなものがあるようです。
(NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 0;
if ([delegate respondsToSelector:@selector(numberOfItemsInSection:)]) {
rows = [delegate numberOfItemsInSection:section];
[tableView beginUpdates];
[tableView endUpdates];
}
}
beginUpdate: / endUpdate: シーケンスを削除すると、問題は魔法のように消えました。
たぶんこれは誰かを助けるでしょう:私はかつて、単一のテーブルビューセルを更新しているときにこのエラーが発生しました. 私は何かをするつもりだった
NSIndexPath *reloadRow = [NSIndexPath indexPathForRow:1 inSection:2];
[self._mainTableView reloadRowsAtIndexPaths:@[reloadWebViewRow]
withRowAnimation:UITableViewRowAnimationFade];
しかし、偶然、私はタイプしました
NSIndexPath *reloadRow = [NSIndexPath indexPathForItem:1 inSection:2];
2 つのインデックスパスの違いに注意してください。一方はindexPathForItem
(間違った) で作成され、もう一方はindexPathForRow
(正しい) で作成されます。これにより、tableView の非常に奇妙な動作と見出しのエラー メッセージが発生しました。
ええと、私はこれを理解しようとして 1 日の大半を費やしただけなので、この別の説明が誰かの時間を節約できることを願っています。
ロード時に時々このメッセージを出すテーブルビューがありました。ビューの読み込み中に発生する Core Data オブジェクトの KVO 通知が原因であることが判明しました。(変更を観察すると、コントローラーは問題のテーブルビューで reloadData を呼び出してみました。ビューの読み込みが完了するまでオブジェクトを観察しないことで修正されました(以前は、アクセサーを介して割り当てられたオブジェクトを観察し始めました)
TLDR: メイン スレッド以外からデータをリロードしようとしていないか確認してください。
もう一つの条件は…
これは、ヘッダーが不要で、 を返したときに発生しましたnil
。
修理:
func tableView(tableView: UITableView,
titleForHeaderInSection section: Int) -> String? {
return ""
}
Web 呼び出しからのコールバックであるコードの一部で UI を更新しようとしたときに、問題が発生したようです。UI の更新をメイン スレッドで強制的に実行することで解決しました。このようなコードを使用しました。
void runOnMainQueueWithoutDeadlocking(void (^block)(void)){
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
バックグラウンド Web 呼び出しの成功ブロック内で次のように呼び出します。
runOnMainQueueWithoutDeadlocking(^{
[self.tableView beginUpdates];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
});