【问题标题】:How to delete object from NSSet in relation one to Many in Core Data using NSFechedResultController?如何使用 NSFechedResultController 从 NSSet 中删除与核心数据中的一对多相关的对象?
【发布时间】:2015-12-19 17:42:30
【问题描述】:

我的核心数据图必须是实体,即 APBook 实体与 APLippingExtract 有一对多的关系。一本书可以有很多剪报。
RootTableViewController,它在部分中显示作者姓名,在行中显示他们的书籍。在 DetailTableViewController 中,从 APClippingExtract 实体中获取数据如下 -

@implementation DetailTableViewController

#pragma mark - fetchedResultController
- (NSFetchedResultsController*) fetchedResultController {

if (_fetchedResultController != nil) {
    return _fetchedResultController;
}

NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"APClippingExtract"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"extract" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

[request setPredicate:[NSPredicate predicateWithFormat:@"extractFromBook == %@", self.currentBook]];

request.fetchBatchSize = 20;
_fetchedResultController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:self.mainContext sectionNameKeyPath:nil cacheName:nil];

//dlegating for NSfetchedResultController
_fetchedResultController.delegate =self;

return _fetchedResultController;
}

当用户删除带有裁剪的行时,下面的方法用于从实体中删除它。

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

if (editingStyle == UITableViewCellEditingStyleDelete) {
    NSManagedObjectContext *context = self.mainContext;
    APClippingExtract *clippingToDelete = [self.fetchedResultController objectAtIndexPath:indexPath];

    [context deleteObject:clippingToDelete];

    [eeCoreStack saveMainContext];

}
}

EECoreStack是Core Stack setUp的自定义类//保存方法如下

- (void)saveMainContext {
[self.mainContext performBlock:^{
    NSError *error = nil;
    [self.mainContext save:&error];
    if(error){
        NSLog(@"ERROR SAVING MAIN MOC %@: %@:", [error localizedDescription], [error userInfo]);
    }else {
        [self saveMasterContext];
    }
}];
}

- (void)saveMasterContext {

    [self.masterContext performBlock:^{
        NSError *error = nil;
        [self.masterContext save:&error];
        if(error){
            NSLog(@"ERROR SAVING MASTER CONTEXT %@; : %@", [error localizedDescription], [error userInfo]);
        }
    }];
}

问题是删除行时,返回 RootTableViewController 时,numberOfClipping 计数没有改变。

APBook类中有一个方法

- (void)removeSmallClippings:(NSSet<APClippingExtract *> *)values;

为了上面的工作,需要获取 APBook 属性。因为我目前正在 DetialTableViewController 中获取 APClippingExtract。

如有错误请指正。

编辑 1:

RootTableViewController

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

if([segue.identifier isEqualToString:@"ListSegue"]){

    ListTableViewController *destination = (ListTableViewController *)segue.destinationViewController;

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    APBook *selectedBook = (APBook*)[self.fetchedResultController objectAtIndexPath:indexPath];

    destination.currentBook = selectedBook;
    destination.mainContext = self.mainContext;
    destination.workerContext = self.workerContext;


    destination.deleteNow = ^(APClippingExtract *deleteClipping){
        [self.mainContext deleteObject:deleteClipping];
        deleteClipping.extractFromBook.numberOfClippings = deleteClipping.extractFromBook.numberOfClippings;
        [eeCoreStack saveMainContext];

    };
}
}

在 DetailTableViewController 中

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete) {

    APClippingExtract *clippingToDelete = [self.fetchedResultController objectAtIndexPath:indexPath];
    self.deleteNow(clippingToDelete);


}

}

【问题讨论】:

  • 我正在使用这种方法从 NSSet 中删除对象,但当我返回 RootTableViewController 时,表格没有更新。 APClippingExtract *clippingToDelete = [self.fetchedResultController objectAtIndexPath:indexPath]; NSMutableSet *mutableSet = [NSMutableSet setWithSet:self.currentBook.smallClippings]; [mutableSet removeObject:clippingToDelete]; self.currentBook.smallClippings = mutableSet; NSLog(@"Sel book clippingis %i", (int)[self.currentBook.smallClippings count]); [eeCoreStack saveMainContext];
  • 在重新加载表格视图后,重新加载时,剪报计数正确显示。但是我们不要使用 NSFetchedResultController 这样我们就不必显式地执行 [tableView reloadData] 了。

标签: objective-c core-data


【解决方案1】:

修改对象(包括删除)不会触发其相关对象的任何更新。这意味着正在监视相关对象的 FRC 不会触发。您要做的就是自己修改相关对象。确切地说,我不知道你有什么属性,但这里有一个例子。

clipping.book.title = clipping.book.title; // This will trigger FRCs watching book entities.

[context deleteObject:clipping];

【讨论】:

  • 您有具体的问题要询问吗?我的回答有什么不清楚的地方吗?
  • 请看Model graph的截图。我已经编辑了我的帖子。重新加载 tableview 可以完成工作,但效率不高。我读过其他帖子,上面说要在两个实体上创建另一个相同类型的属性。
  • 我正在尝试通过 deleteClipping.extractFromBook.numberOfClippings = deleteClipping.extractFromBook.numberOfClippings 来更新 FRC。它不工作。
  • 我正在将 APClipping 对象发送回 RootViewController 以保证我保存上下文的位置,即使在更新 FRC 之后,如您提到的那样,TableView 中没有任何变化。它仅在我关闭应用程序并重新启动时才有效。
  • 您确定APBook 的FRC 已触发,您是否处理NSFetchedResultsChangeDelete 事件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多