UITableViewで奇妙な問題が発生しました:reloadRowsAtIndexPaths:withRowAnimation:
を使用して特定の行を再読み込みしましたが、一見無関係な例外でアプリがクラッシュします:NSInternalInconsistencyException-セクションに存在するよりも多くの行を削除しようとしました。 ==
私のコードは次のようになります:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
そのreloadRowsAtIndexPaths:withRowAnimation:
メッセージを単純なreloadData
に置き換えると、完全に機能します。
何か案は?
問題は、おそらくテーブルのサイズを変更したことです。たとえば、テーブルビューのソースデータを追加または削除したとします。
その場合、reloadData
を呼び出すと、セクションのサイズとそのセクションの数を含めて、テーブルが完全に再ロードされます。
ただし、_reloadRowsAtIndexPaths:withRowAnimation:
_を呼び出すと、テーブルビューのパラメータは再ロードされません。これにより、次の問題が発生します。セルテーブルを再読み込みしようとしているときに、テーブルビューのサイズを確認し、変更されていることを確認します。その結果、クラッシュします。この方法は、セルのビューを再読み込みしたくない場合にのみ使用できます(たとえば、ラベルが変更された場合や、サイズを変更したい場合)。
ここで、テーブルビューから/テーブルビューにセルを削除/追加する場合は、次のアプローチを使用する必要があります。
beginUpdates
のメソッドUITableView
を呼び出して、サイズが変更されることをテーブルに通知します- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
を使用して新しい行を挿入することについて通知します- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
を使用して行を削除することについて通知しますendUpdates
のメソッドUITableView
を呼び出して、サイズが変更されたことをテーブルに通知しますお役に立てば幸いです
次のコードが機能すると思います。
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
この問題は、reloadRowsAtIndexPaths:withRowAnimation:を呼び出すブロックと、reloadDataを呼び出す並列スレッドが原因で発生していました。クラッシュは、numberOfRowsInSectionとnumberOfSectionsをサニティチェックしたにもかかわらず、reloadRowsAtIndexPaths:withRowAnimationが空のテーブルを見つけたことが原因でした。
例外が発生しても気にしないという態度でした。アプリ全体がクラッシュするよりも、アプリのユーザーとして一緒に暮らすことができる視覚的な破損。
これが私の解決策であり、喜んで共有し、建設的な批判を歓迎します。より良い解決策があれば、私はそれを聞きたがっていますか?
- (void) safeCellUpdate: (NSUInteger) section withRow : (NSUInteger) row {
// It's important to invoke reloadRowsAtIndexPaths implementation on main thread, as it wont work on non-UI thread
dispatch_async(dispatch_get_main_queue(), ^{
NSUInteger lastSection = [self.tableView numberOfSections];
if (lastSection == 0) {
return;
}
lastSection -= 1;
if (section > lastSection) {
return;
}
NSUInteger lastRowNumber = [self.tableView numberOfRowsInSection:section];
if (lastRowNumber == 0) {
return;
}
lastRowNumber -= 1;
if (row > lastRowNumber) {
return;
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
@try {
if ([[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] == NSNotFound) {
// Cells not visible can be ignored
return;
}
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
@catch ( NSException *e ) {
// Don't really care if it doesn't work.
// It's just to refresh the view and if an exception occurs it's most likely that that is what's happening in parallel.
// Nothing needs done
return;
}
});
}
THIS IS OLD。使用しないでください。セルをUITextField
を含む編集セルに変更するために、reloadRowsAtIndexPaths...
を呼び出していたときにこの問題にぶつかりました。 。エラーは、テーブル内のすべての行を削除していることを示していました。問題を解決するために、次のものを削除しました。
[self.tableView beginUpdates];
NSArray *reloadIndexPath = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:count inSection:section]];
[self.tableView reloadRowsAtIndexPaths:reloadIndexPath withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
と置き換えました
[self.tableView reloadData];
何度も試した結果、「reloadRowsAtIndexPaths」は、セルの内容を変更するだけで、セルを挿入または削除しない場合にのみ、特定の場所で使用できることがわかりました。包んでもどこでも使えない
_[self beginUpdates];
//reloadRowsAtIndexPaths
[self endUpdates];
_
それを使用できると私が見つけた場所は次のとおりです。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath - (IBAction) unwindToMealList: (UIStoryboardSegue *) sender
「viewDidLoad」や「viewDidAppear」から呼び出すなど、他の場所から試行しても、効果がないか(つまり、すでにロードされているセルの場合、リロードは効果がありません)、例外が発生します。
したがって、「reloadRowsAtIndexPaths」はそれらの場所でのみ使用するようにしてください。
私も同じ問題を抱えていました。私の場合;これは、別のビューコントローラーが既存のテーブルビューコントローラーをポップ/プッシュしてから[self.tableViewreloadRowsAtIndexPaths]関数が呼び出された場合にのみ発生していました。
reloadRowsAtIndexPaths呼び出しは、30を超える視覚的に複雑な行を持つテーブルビューで、さまざまな行を非表示/表示していました。この問題を修正しようとすると、テーブルビューアプリを少しスクロールしてもクラッシュしなかったことがわかりました。また、セルを非表示にしない場合(高さとして0を返すことにより)、クラッシュしませんでした
この問題を解決するには、「(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath」関数を変更し、行の高さとして少なくとも0.01を返しました。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
return rowModel.height + 0.01; // Add 0.01 to work around the crash issue.
}
それは私にとって問題を解決しました。
リロードする前にセルの可視性を確認する必要があります。ここにSwift 3コード:
let indexPath = IndexPath(row: offset, section: 0)
let isVisible = tableView.indexPathsForVisibleRows?.contains{$0 == indexPath}
if let v = isVisible, v == true {
tableView.reloadRows(at: [indexPath], with: .automatic)
}
TableViewにいくつかの変更を加えたため、アプリがクラッシュします。 tableViewにいくつかの行を追加または削除しました。したがって、View Controllerがモデルコントローラークラスにデータを要求すると、indexPathsに不一致があります。 indexPathsが変更後に変更されたため。
つまり、単に通話を削除するだけです
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
またはそれを置き換えます
[self.tableView reloadData];
ReloadDataを呼び出すと、セクションの数、各セクションの行の数がチェックされ、すべてがリロードされます。