![](/img/trans.png)
[英]CoreData UITableViewController managedObjectContext Error
[英]Deleting records in UITableViewController throws error
问题:当我单击给定表/节行的删除按钮时,出现以下错误:“ ***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0节中的行数无效。更新(4)之后在现有节中包含的行数必须等于更新(4)之前在该节中包含的行数,加上或减去从该节插入或删除的行数(已插入0) ,其中1个已删除)。
从我已阅读过的有关此症状的其他文章中,我收集到的信息是我想手动删除数据源数组中的一个元素,但不确定如何在此方法中访问该节的数组:
// COMMIT EDITING STYLE
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"indexPath: %@", indexPath);
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates]; // throws error here
[tableView reloadData];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
我认为这种情况的复杂性是由于以下事实而引起的:我正在从应用程序中拉出plist(FormEntries.plist)来保存用户输入的数据,因此我必须为每个应用程序进行调用和过滤部分。 可以很好地填充UITableView及其所有部分,但是由于在每个部分内以及内部都创建了一个新的过滤数组,因此我不确定如何再次访问它以删除该元素,从而纠正了上述问题错误信息。 这是我为每个表部分加载数据的方式:
// CELL FOR ROW AT INDEXPATH
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSNumber *numScreenId = [[arrayOfModulesScreens objectAtIndex: indexPath.section] objectForKey: @"id"];
NSMutableArray *arrayRecords = [epFrameWork selectPlist: @"FormEntries" filterByKey: @"screen_id" keyValue:numScreenId];
NSString *strTitle = [[arrayRecords objectAtIndex: indexPath.row] objectForKey: @"storage_string"];
cell.textLabel.text = strTitle;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
-不确定这是否有助于诊断,但是在这里仍然如此-
// TITLE FOR HEADER IN SECTION
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[arrayOfModulesScreens objectAtIndex: section] objectForKey: @"screen_title"];
}
// NUMBER OF SECTIONS IN TABLE VIEW
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrayOfModulesScreens count];
}
// NUMBER OF ROWS IN SECTION
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSNumber *numScreenId = [[arrayOfModulesScreens objectAtIndex: section] objectForKey: @"id"];
NSMutableArray *arrayRecords = [epFrameWork selectPlist: @"FormEntries" filterByKey: @"screen_id" keyValue:numScreenId];
int rowCount = [arrayRecords count];
return rowCount;
}
解决这种情况或解决上面发布的错误消息的最佳方法是什么?
-更新-
因此,这是我尝试确定要删除的plist记录的方式,假设这是解决原始错误所需的操作:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
int g = indexPath.row;
int count = -1;
UITableViewCell *tvc = [[UITableViewCell alloc] init];
for(id element in tableView.subviews) {
if([element isKindOfClass:[UITableViewCell class]]) {
count +=1;
NSLog(@"g: %d - count: %d", g , count);
if(count == g) {
tvc = element;
NSLog(@"tvc: %@ - UID: %@ - g: %d - count: %d", tvc, tvc.detailTextLabel.text, g , count);
}
}
}
我的逻辑是在cellForRowAtIndexPath方法中的tvc.detailTextLabel.text上设置一个隐藏的唯一标识符,这反过来又让我知道要过滤和删除plist中的哪个记录,方法是调用[array removeObjectAtIndex:uid],其中已过滤掉array plist数组。 现在唯一的问题是,NSLog中的tvc总是返回索引0处的记录,而不是包含我单击的删除按钮的行。
NSLog返回:tvc:<UITableViewCell:0x713e2c0; 框架=(0 30; 320 44); 文字=“教堂A”; autoresize = W; 层= <CALayer:0x7113e70>>-UID:-237206321-g:3-计数:3.那么为什么当tvc为索引3时,tvc返回索引0我单击了删除按钮?
这仅仅是变成一团糟,还是有一个更清洁的解决方案? 但是,你还是很困惑。
此错误肯定与您对要加载到表中的数据的处理不当有关。 我发现处理表内容修改的最简单,最安全的方法是根据需要进行一些调整(在tableView:commitEditingStyle:之内)
//REMOVE A CELL FROM A SECTION
[yourTable beginUpdates];
[yourTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
[yourTable endUpdates];
[yourTable reloadData];
另外,您需要确保正确更新了阵列以使更改反映在表中。
这就是我最终能够解决此问题的方式:
我改变了所有这些废话:
int g = indexPath.row;
int count = -1;
UITableViewCell *tvc = [[UITableViewCell alloc] init];
for(id element in tableView.subviews) {
if([element isKindOfClass:[UITableViewCell class]]) {
count +=1;
NSLog(@"g: %d - count: %d", g , count);
if(count == g) {
tvc = element;
NSLog(@"tvc: %@ - UID: %@ - g: %d - count: %d", tvc, tvc.detailTextLabel.text, g , count);
}
}
}
简单的一行:
UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];
这使我能够确定正在使用的单元。 所以我最终的有效代码如下所示:
// COMMIT EDITING STYLE
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];
[epFrameWork deleteRecordFromPlist:@"FormEntries" uid:cell.detailTextLabel.text];
[tableView reloadData];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
-(void) deleteRecordFromPlist:(NSString *)plist uid:(NSString *)uId {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tmpFileName = [[NSString alloc] initWithFormat:@"%@.plist", plist];
NSString *path = [documentsDirectory stringByAppendingPathComponent:tmpFileName];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
NSDictionary *dict = [[NSDictionary alloc] init];
NSString *tmpUid;
for(int i=0; i < [array count]; i++) {
dict = [array objectAtIndex:i];
tmpUid = [dict valueForKey:@"uid"];
if([tmpUid isEqualToString:uId]) {
[array removeObjectAtIndex:i];
[array writeToFile:path atomically:YES];
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.