【发布时间】:2013-11-19 12:15:45
【问题描述】:
我已经解决这个问题很多天了,我需要帮助,因为我不知道如何继续。我面临的问题(当您阅读这个问题时会变得更清楚)是我不确定如何获取现有的 NSManagedObject 如果它在创建新对象时已经存在。
我们退一步看一下Model,app的前提很简单;允许用户创建具有名称、金额、场合和日期的“交易”——在创建新交易时,应允许用户选择现有名称。数据模型:
- 具有 wasGiven 属性的事务实体
- 具有名称属性的人员实体
- 具有标题属性的场合实体
- 具有金额属性的项目实体
事务与 Person 实体 (whoBy) 有关系,有与 Occasion 实体 (occasion) 的链接以及与 Item 实体 (itemType) 的链接。
该应用程序是一个简单的 2 个选项卡式表视图控制器 - 第一个选项卡包含所有信息,按日期划分。第二个选项卡仅包含“名称”信息。有一个加号按钮,当用户按下它时,他们会看到一个模态视图以添加名称、场合、金额和日期。他们按下保存并将其保存到核心数据数据库。
问题 创建一个具有新名称的新事务可以完美地创建这一点。 使用现有名称创建新事务(用户手动输入相同的名称)会在第一个选项卡中创建一个新对象作为单独的条目(正确),但在名称选项卡中,它会为该人创建一个重复的名称。当您单击其中一个重复名称时,它会显示两个交易。这里的问题是它看起来每次都在创建一个新的 Person 对象而不是引用。
代码
我已经经历了多次迭代来尝试让它工作,这里是最新的代码,使用 NSManagedObject 的子类。
managedObjectContext 是从 App Delegate 获得的。
名称、事件、金额和日期存储在各自的文本字段中。
AddEntry.m - 保存方法
- (IBAction)save:(id)sender
{
NSManagedObjectContext *context = [self managedObjectContext];
Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context];
Item *itemType = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:context];
Person *p = (Person *)[Person personWithName:self.nameTextField.text inManagedObjectContext:context];
Occasion *o = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text andEventDate:self.dateTextField.text inManagedObjectContext:context];
transaction.whoBy = p;
occasion.title = self.occasionTextField.text;
transaction.occasion = o;
itemType.amount = self.itemTextField.text;
transaction.item = itemType;
transaction.wasReceived = @(self.isReceivedSegment.selectedSegmentIndex == 0);
NSError *error = nil;
if (![context save:&error])
{
NSLog(@"Can't save! %@ %@", error, [error localizedDescription]);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
这当然调用了 Person NSManagedObject 子类,这是我经历了几次迭代的地方。
Person NSManagedObject 子类 - 迭代 1 - 谓词
+ (Occasion *)eventWithName:(NSString *)title andEventDate:(NSString *)date inManagedObjectContext:(NSManagedObjectContext *)context;
{
Occasion *occasion = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Occasion"];
request.predicate = [NSPredicate predicateWithFormat:@"title = %@", title];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *occasions = [context executeFetchRequest:request error:&error];
if (!occasions)
{
// Handle Error
}
else if (![occasions count])
{
occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" inManagedObjectContext:context];
occasion.title = title;
}
else
{
occasion = [occasions lastObject];
}
occasion.dateOfEvent = date;
return occasion;
}
问题 这有点工作。我放置了一个断点,如果对象已经存在并且如果它是一个新对象,则返回到此处和添加条目中的保存方法的返回“人”是相同的,但是当涉及到第二个选项卡时,它仍然是为同一个人添加第二个条目。
迭代 2 - objectID
在尝试获取对象 ID 时,我在第二个选项卡中得到了相同的重复条目结果:
+ (Person *)personWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context;
{
Person *person;
NSManagedObjectID *personID = person.objectID;
if (!personID)
{
person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
person.name = name;
return person;
}
else
{
return person;
}
}
如果重要的话,第二个选项卡的 fetchRequest 如下:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Occasion" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
编辑 我想知道我在第二个选项卡 fetchRequest 中没有谓词这一事实是否意味着它正在说明所有对象..
当然,我会在未来对此进行验证,因为在第一个选项卡中,当我单击一个单元格时,我希望传递该“交易”,以便我可以编辑该字段。
这让我发疯了,真的阻止了我的应用程序的进展,所以这里的任何帮助都将不胜感激!
编辑:包含数据模型
【问题讨论】:
-
您是否调试过“它仍在为同一个人添加第二个条目” - 列表中的同一个 MO 是否两次?或者你有 2 个同名?
-
嗨@Wain 好问题 - 我必须检查一下 - 使用现有名称时,相同的返回人在那里,但这并不意味着 MO 是相同的 - 会是什么最好的调试方法?
-
如果我理解正确,“whoBy”就是关系。它是如何定义的?
-
从 FRC 记录
fetchedObjects -
@AntonijoDev 绝对 - Transaction 与 Person 实体具有 whoBy 关系.. 所以 transaction.whoBy.name 正在进入 Person 实体以收集 name 属性.. Person (transactions) >交易(whoBy) - 希望这会有所帮助
标签: ios uitableview core-data nspredicate nsfetchrequest