我已经阅读了Apple开发人员指南和教程,并且我浏览了2本关于Core Data主题的iPhone书籍。
我习惯于处理事物的“价值对象”/“实体”方面,然后将它们发送到网络服务或类似服务。但在iPhone上,我自己处理所有事情......残酷的世界:)
来自Apple Developer网站的Locations
,TaggedLocations
和PhotoLocations
示例并未以我可以“计算”的方式向我提供答案。我希望有人能够启发我。
我使用datamodel GUI设置了我的模型。两个实体Person
和Dream
。
Person
具有personName
字符串属性和一对多dreams
关系。
Dreams
具有description
字符串属性和一对一person
关系。
我一直在设置一个简单的tableView
应用。
第一个视图是人员列表,第二个视图是他们的梦想列表。
这是我将人添加到modelObjectContext
:
Person *newPerson = (Person *)[NSEntityDescription
insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:managedObjectContext];
[newPerson setPersonName:@"Ben Hur"];
好的,然后我在上下文中添加了一个新的梦想:
Dream *newDream = (Dream *)[NSEntityDescription
insertNewObjectForEntityForName:@"Dream"
inManagedObjectContext:managedObjectContext];
[newDream setDescription:@"I had a nightmare"];
我现在将梦想添加到这样的人:
[newPerson addDreamObject:newDream];
这对我来说有点模糊,因为xcode在Person
类上为我生成了不同的方法/访问器:
@class Dream;
@interface Person : NSManagedObject
{
}
@property (nonatomic, retain) NSString * personName;
@property (nonatomic, retain) NSSet* dream;
@end
@interface Person (CoreDataGeneratedAccessors)
- (void)addDreamObject:(Dream *)value;
- (void)removeDreamObject:(Dream *)value;
- (void)addDream:(NSSet *)value;
- (void)removeDream:(NSSet *)value;
@end
在其他情况下,我无需处理实际的保存,检索和数据。我会构建一个名为person
的实体/值对象,并给它一个Array
来存储梦想。但是这不是核心数据中可能的属性类型,而不是这样做的方式,我已经读过了(在这里也是类似的线程)。
那么样板代码如何工作?
我应该使用addDream
并发送一个充满梦想的NSSet
吗?或者我可以只信任核心数据来实例化这个并且专门使用addDreamObject
发送Person
类型的Dreams
实体对象吗?
我还使用xcode的样板代码保存上下文。 现在我希望用这个人更新观点,更确切地说是他的名字。
在cellForRowAtIndexPath
方法中我给出了这个:
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:@"personName"] description];
一切都很顺利,名字也显示在名单上。
我设置DreamViewController
以Person
对象作为参数。
Person *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
dreamView.selectedPerson = selectedObject;
然后我将viewController
推到堆栈上,然后输入DreamView
。在这里,我似乎无法了解与我“发送”的观点有关的梦想。
这就是我在DreamViewController
的{{1}}方法中尝试的方法(viewDidLoad
是我用来传递selectedPerson
对象的访问器):
Person
我似乎无法掌握这一点,而且我目前使用Objective C的经验不允许我从Apple的文档中获取“最佳实践”本质。
答案 0 :(得分:3)
首先,您需要纠正自己在模型中犯下的错误。你的梦想实体中不能有一个名为“描述”的属性:这是禁止的,因为“描述”它是方法的名称。
从Apple文档(核心数据编程指南):
请注意,属性名称不能与NSObject或NSManagedObject的任何无参数方法名称相同,例如,您不能为属性指定名称“description”(请参阅NSPropertyDescription)。
addDreamObject:和addDream:之间的区别在于前者用于在to-many关系中插入Dream对象,而后者用于插入或替换to-many关系的上下文。
你不应该使用
cell.textLabel.text = [[managedObject valueForKey:@"personName"] description];
你应该简单地使用
cell.textLabel.text = [managedObject valueForKey:@"personName"];
关于与您的人相关的梦想,您不需要额外的获取请求。一旦掌握了人物对象,您就可以按如下方式访问该人的梦想:
for(Dream *dream in person.dreams){
// process your Dream object
}
最后,不清楚为什么不将托管对象上下文显式传递给DreamViewController作为实例变量。这是常见的做法,也在Apple示例代码中显示。另一个错误是检查
if (fetchedObjects == nil)
因为如果查询实际上没有找到任何对象,则返回nil是合法的;你必须检查你的NSError对象是否不是nil(你必须在执行你的获取请求之前将它初始化为nil):
if(error)
声明
NSLog(@"The Dream object says: %@", [d description]);
甚至可能会使您的应用程序崩溃,正如我在回答的开头所解释的那样。