我是 Core Data 的新手。我有两个实体:USER
和 IOU
。
// 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/