ios - 使用核心数据执行此操作的 "right"方法是什么(更新多个实体)

标签 ios cocoa-touch core-data

我是 Core Data 的新手。我有两个实体:USERIOU

// User.h
@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) NSSet<NSManagedObject *> *ious;

// Iou.h
@property (nullable, nonatomic, retain) NSDecimalNumber *amount;
@property (nullable, nonatomic, retain) NSDate *date;
@property (nullable, nonatomic, retain) NSString *iouDescription;
@property (nullable, nonatomic, retain) User *user;

在 View Controller 中,我使用谓词来获取属于用户的 ious,然后使用它来获取用户的名称。然后,我显示该用户的姓名以及她的 ious 列表。

// PersonViewController.m
// Fetch Request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Iou"];

// Predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@",   @"user.name", self.userName];
[fetchRequest setPredicate:predicate];

// Execute fetch request
NSError *error = nil;

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;

[self.fetchedResultsController performFetch:&error];

Iou *iou = self.fetchedResultsController.fetchedObjects.lastObject;
self.user = iou.user;

接下来,我的客户可以点击借条并编辑借条和用户。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    Iou *iou = [self.fetchedResultsController objectAtIndexPath:indexPath];
    personEditViewController.user = self.user;
    personEditViewController.iou = iou;
    personEditViewController.managedContext = self.managedContext;
    [[self navigationController] pushViewController:personEditViewController animated:YES];
}

以下是我编辑 USER 实体和 IOU 实体的方法。

// PersonEditViewController.m
self.user.name = self.nameField.text;

// Description
self.iou.iouDescription = self.descriptionField.text;

// Date
UIDatePicker *datePicker = (UIDatePicker *)self.dateField.inputView;
self.iou.date = datePicker.date;

// Save
NSError *error;
[self.iou.managedObjectContext save:&error];

我使用 NSFetchedResultsController 来处理 UITableView。如果我更改 IOU 属性,我会得到正确的行为。我得到 NSFetchedResultsChangeMove;但是,如果我还更新了 USER,我会得到 NSFetchedResultsChangeDelete。如果我重新启动,数据看起来很好,所以它只发生在 View 中。

我搜索了一些SO问题,但我仍然不明白。有什么简单的模式可以使用,这样它每次都会有效。

我考虑过不使用NSFetchedResultsController,而是依靠带有UITableView的旧式NSArray。在这种情况下,每次我对记录进行增删改查时,它都会从数据库中重新获取记录,我将使用 fetchedResultsController.fetchedObjects

最佳答案

如果修改 User 对象的 name 属性,它将不再匹配谓词 - 因此 FRC 将触发 delete 以删除 TableView 。 (请注意,您可能希望删除所有其他行,因为它们也不再满足谓词,但 FRC 仅重新评估那些已更新的 IOU)。

如果您想避免这种情况,请修改您的获取结果 Controller 代码以首先获取与谓词匹配的 User 对象,然后修改 FRC 谓词以测试是否 IOU 属于这些用户中的任何一个:

// PersonViewController.m
NSError *error = nil;
NSFetchRequest *userFetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"User"];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"%K == %@",   @"name", self.userName];
userFetchRequest.predicate = userPredicate;
NSArray *matchingUsers = [self.managedContext executeFetchRequest:userFetchRequest error:&error];
// Fetch Request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Iou"];

// Predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K IN %@",   @"user", matchingUsers];
[fetchRequest setPredicate:predicate];

// Execute fetch request
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;

[self.fetchedResultsController performFetch:&error];

Iou *iou = self.fetchedResultsController.fetchedObjects.lastObject;
self.user = iou.user;

由于 FRC 的谓词是基于 User 对象本身,而不是它的任何属性,您可以修改这些属性而不会导致其 IOU 无法满足FRC 的谓词。

关于ios - 使用核心数据执行此操作的 "right"方法是什么(更新多个实体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33633767/

相关文章:

ios - 如何将核心数据实体导出到 CSV 文件

ios - 核心数据更新记录改为插入

swift - AppDelegate 类型的值在 swift 4 中没有成员 managedObjectContext

iphone - 无法从 Xcode 项目中删除启动图像

ios - 将局部变量分配给属性时的内存泄漏弧

ios - 如何更改 Firebase Analytics for iOS 中的最小 session 持续时间值?

ios - 如何禁用手动对角滚动同时启用对角 setContentOffset 滚动动画

cocoa-touch - 在 Cocoa 和 Cocoa Touch 中将 CGPoint 存储在 NSArray 中的通用解决方案?

iphone - 核心数据: Serious application error

ios - BLE外设吞吐量限制