我一直在研究这个问题很多天,我需要帮助,因为我不知道该怎么办。我所面临的问题(当你阅读这个问题时会变得更清楚)是我不确定如果现有的NSManagedObject在创建新的NSManagedObject时已经存在。
让我们退一步看看模型,应用程序的前提很简单;允许用户创建具有名称,金额,场合和日期的“交易” - 在创建新交易时,应允许用户选择现有名称。数据模型:
事务与Person实体(whoBy),Occasion Entity(场合)的链接以及Item Entity(itemType)的链接有关系。
App是一个简单的2 Tabb-ed表视图控制器 - 第一个选项卡包含所有信息,按日期划分。第二个选项卡仅包含“名称”信息。有一个加号按钮,当用户按下它时,它们会显示一个模态视图,以添加名称,场合,数量和日期。他们按保存并将其保存到核心数据数据库。
问题 使用新名称创建新事务可以完美地创建。 使用现有名称创建新事务(用户手动键入相同的名称)会在第一个选项卡中创建一个新对象作为单独的条目(正确),但在名称选项卡中,它会为该人员创建一个重复的名称。单击任一重复名称时,它会显示两个事务。这里的问题是它看起来像每次创建一个新的Person对象而不是引用。
代码
我已经通过MULTIPLE迭代尝试使其工作,这是最新的代码,使用NSManagedObject的子类。
从App Delegate获取managedObjectContext。
名称,事件,金额和日期存储在自己的文本字段中。
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 Subclass - Iteration 1 - Predicates
+ (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;
}
问题 这有点奏效。我放置了一个断点,返回的“person”在这里返回并且添加条目中的save方法如果对象已经存在则是相同的,如果是新对象则是new,但是当它到达第二个选项卡时,它仍然是为同一个人添加第二个条目。
迭代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中没有谓词这一事实意味着它说明了所有对象..
当然,我将来会证明这一点,因为在第一个标签中,当我点击一个单元格时,我想让“交易”通过,以便我可以编辑该字段。
这让我发疯,并且真的阻止了我的应用程序的进展,所以这里的任何帮助都会受到大力赞赏!
编辑:包含数据模型
答案 0 :(得分:1)
好的,这就是发生的事情......你添加第一个交易,一个名字U提供杰克,然后你添加第二个交易(T进一步在文本中)并添加名称约翰,在你添加名字杰克的第三个T并添加另一个名叫约翰。如果你看看数据库中的表,你会看到Transitions表有4个条目因为你添加了4个转换,但是Persons只有两个。它有两个原因你在Persons输入上添加了一个过滤器,因此它不能包含两个相同的名称。你犯的错误是你试图从Transition表中获取所有条目。当然U得到4个名字(2个Johns和2个Jacks)导致Transition表中有R 4个条目,每个条目都与Person记录相关联。如果你想要获取所有人,你不应该从Transition表中获取它,你应该从Persons表中执行它或者你应该添加[r setReturnsDistinctResults:YES];如果U R从Transition表中获取,你的获取请求...我认为有一种方法可以设置不同的属性,但我不知道语法。所以问题实际上在你想做什么,你想要呈现你的数据库中的所有人,或者你想在你的过渡上呈现名字,这意味着同一个人可以做出不同的过渡。见......
答案 1 :(得分:0)
我认为你有Transaction<< -Person所以在事务管理对象中,由于这种关系,你有一组人。当您将相同的人添加到事务时,它会创建一个新的托管对象并将其添加到集合中,如果您按名称获取,您将拥有多个具有相同名称的事务记录,但这并不意味着您有多个人。直接在Persons表上进行获取,您将看到值是不同的......
我建议您安装类似Firefox的东西并使用sqlLiteManager在数据库本身中占据一席之地......