ios核心数据:确保从数据源中删除对象
更新:在评论中有人指出我不必要地调度到主线程。在删除调度和不必要的ios核心数据:确保从数据源中删除对象,ios,objective-c,uitableview,core-data,nsfetchrequest,Ios,Objective C,Uitableview,Core Data,Nsfetchrequest,更新:在评论中有人指出我不必要地调度到主线程。在删除调度和不必要的开始/结束更新之后,现在当我尝试删除单元格时,它使用casensfetchedresultschangediate(与nsfetchedresultschangedite相反)调用configureCell 使程序崩溃的行是CollectedLeaf*theCollectedLeaf=[collectionfetchedresultscoontroller objectAtIndexPath:indexPath]在下面的方法中。崩
开始/结束更新之后
,现在当我尝试删除单元格时,它使用casensfetchedresultschangediate
(与nsfetchedresultschangedite
相反)调用configureCell
使程序崩溃的行是CollectedLeaf*theCollectedLeaf=[collectionfetchedresultscoontroller objectAtIndexPath:indexPath]代码>在下面的方法中。崩溃日志是,节列表中索引20处没有节
- (void)configureCell:(SpeciesCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
CollectedLeaf* theCollectedLeaf = [collectionFetchedResultsController objectAtIndexPath:indexPath];
[cell setCollectedLeaf:theCollectedLeaf];
}
每次从表中删除单元格时,我都会收到一个无效更新:节中的行数无效错误。我在controllerDidChangeContent
中的[\u table endUpdates]
处获得断点
在许多SO POST中,出现此错误的原因是,在从表中删除行之前,对象尚未从数据源中删除。我在committeeditingstyle
中从数据源中删除对象,该对象在didChangeObject
中的deleteRowsAtIndexPaths
之前调用
尽管我下了命令,但我仍然得到无效更新
,这一事实让我认为我没有正确/成功地从数据源中删除它。我还是iOS新手-如何确保从我的核心数据中删除对象
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[_table beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
switch(type) {
case NSFetchedResultsChangeInsert:
[_table beginUpdates];
[_table insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
[_table endUpdates];
break;
case NSFetchedResultsChangeDelete:
NSLog(@"delete called");
[_table deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
// [self configureCell:[_table cellForRowAtIndexPath:indexPath]
// atIndexPath:indexPath];
[_table reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
NSLog(@"fetched update");
break;
case NSFetchedResultsChangeMove:
[_table deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[_table insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[_table insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[_table deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
break;
case NSFetchedResultsChangeUpdate:
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[_table endUpdates];
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(_segmentedControl.selectedSegmentIndex == 1) {
NSLog(@"index path at editingStyleForRowAtIndexPath %@", indexPath);
return UITableViewCellEditingStyleDelete;
}
return NULL;
}
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
// [super tableView: tableView didEndEditingRowAtIndexPath:indexPath];
if(_segmentedControl.selectedSegmentIndex == 1) {
for (UITableViewCell *cell in [_table visibleCells]) {
for (UIView *subview in cell.contentView.subviews)
[subview.layer removeAllAnimations];
}
}
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
/*Only allow deletion for collection table */
if(_segmentedControl.selectedSegmentIndex == 1) {
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSLog(@"index path at commitediting style %@", indexPath);
CollectedLeaf* collectedLeaf = [collectionFetchedResultsController objectAtIndexPath:indexPath];
LeafletPhotoUploader * leafletPhotoUploader = [[LeafletPhotoUploader alloc] init];
leafletPhotoUploader.collectedLeaf = collectedLeaf;
if([LeafletUserRegistration isUserRegistered]) {
[leafletPhotoUploader deleteCollectedLeaf:collectedLeaf delegate:self];
}
// Delete the managed object for the given index path
NSManagedObjectContext *context = [collectionFetchedResultsController managedObjectContext];
[context deleteObject:[collectionFetchedResultsController objectAtIndexPath:indexPath]];
// Save the context.
NSError *error;
if (![context save:&error])
{
NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0)
{
for(NSError* detailedError in detailedErrors)
{
NSLog(@" DetailedError: %@", [detailedError userInfo]);
}
}
else
{
NSLog(@" %@", [error userInfo]);
}
}
}
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"speciesCell";
SpeciesCell* speciesCell = (SpeciesCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[self configureCell:speciesCell atIndexPath:indexPath];
speciesCell.labelCheckMark.backgroundColor = [UIColor blackColor];
return speciesCell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
id <NSFetchedResultsSectionInfo> sectionInfo = [[collectionFetchedResultsController sections] objectAtIndex:section];
if([sectionInfo numberOfObjects] == 0){
UILabel *noDataLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, tableView.bounds.size.height)];
noDataLabel.text = @"Press the Snap It! tab to start collecting!";
//Start your collection by tapping on the Snap It! tab.";
noDataLabel.textColor = [UIColor whiteColor];
noDataLabel.textAlignment = NSTextAlignmentCenter;
tableView.backgroundView = noDataLabel;
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
return [sectionInfo numberOfObjects];
}
-(void)controllerWillChangeContent:(NSFetchedResultsController*)控制器
{
//fetch控制器即将开始发送更改通知,因此请准备表视图以进行更新。
[_表开始更新];
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeObject:(id)一个对象
atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)类型
newindepath:(nsindepath*)newindepath{
开关(类型){
案例NSFetchedResultsChangesInsert:
[_表开始更新];
[_tableinsertrowsatindexpath:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
[_tableendupdates];
打破
案例NSFetchedResultsChangeDelete:
NSLog(@“删除调用”);
[_tabledeleteRowsatindExpath:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeUpdate:
//[自配置单元格:[[表单元格FORROWATINDEXPATH:indexPath]
//atIndexPath:indexath];
[_tablereloadrowsatindexpath:@[indexath]with rowanimation:UITableViewRowAnimationAutomatic];
NSLog(@“获取的更新”);
打破
案例NSFetchedResultsChangeMove:
[_tabledeleteRowsatindExpath:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[_tableinsertrowsatindexpath:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
}
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeSection:(id)sectionInfo atIndex:(nsInteger)ChangeType的sectionIndex:(NSFetchedResultsChangeType)类型
{
开关(类型)
{
案例NSFetchedResultsChangesInsert:
[_tableinsertSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]with RowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeDelete:
[_tabledeleteSections:[NSIndexSet indexetwithindex:sectionIndex]withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeMove:
打破
案例NSFetchedResultsChangeUpdate:
打破
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController*)控制器
{
[_tableendupdates];
}
-(UITableViewCellEditingStyle)tableView:(UITableView*)tableView editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath
{
如果(_segmentedControl.selectedSegmentIndex==1){
NSLog(@“EditingStyleForRowatingIndexPath%@”处的索引路径,indexPath);
返回UITableViewCellEditingStyleDelete;
}
返回NULL;
}
-(void)tableView:(UITableView*)tableView diddeditingrowtaindexpath:(nsindepath*)indepath
{
//[super tableView:tableView didendeditingrowtaindexpath:indexath];
如果(_segmentedControl.selectedSegmentIndex==1){
对于(UITableViewCell*单元格在[\u表visibleCells]中){
用于(UIView*cell.contentView.subview中的子视图)
[subview.layer removeAllAnimations];
}
}
}
//替代以支持编辑表格视图。
-(void)tableView:(UITableView*)tableView提交的编辑样式:(UITableViewCellEditingStyle)行的编辑样式索引路径:(NSIndexPath*)索引路径
{
/*仅允许删除集合表*/
如果(_segmentedControl.selectedSegmentIndex==1){
如果(editingStyle==UITableViewCellEditingStyleDelete)
{
NSLog(@“提交样式的索引路径%@”,indexath);
CollectedLeaf*CollectedLeaf=[collectionFetchedResultsController对象索引路径:indexPath];
传单照片上传器*传单照片上传器=[[传单照片上传器alloc]init];
传单Photouploader.collectedLeaf=collectedLeaf;
如果([传单用户注册为用户注册]){
[传单照片上载器删除collectedLeaf:collectedLeaf代理:self];
}
//删除给定索引路径的托管对象
NSManagedObjectContext*上下文=[collectionFetchedResultsController managedObjectContext];
[上下文删除对象:[collectionFetchedResultsController对象索引路径:indexPath]];
CollectedLeaf* theCollectedLeaf = nil;
if ([[collectionFetchedResultsController sections] count] > [indexPath section]){
id <NSFetchedResultsSectionInfo> sectionInfo = [[collectionFetchedResultsController sections] objectAtIndex:[indexPath section]];
if ([sectionInfo numberOfObjects] > [indexPath row]){
theCollectedLeaf = [collectionFetchedResultsController objectAtIndexPath:indexPath];
//do whatever else I need, delete the object, etc
}
}