【发布时间】:2014-01-17 19:02:02
【问题描述】:
希望您能帮助解决核心数据应用程序中的问题。我把它归结为基本要素:
这是伪代码(本文中要遵循的真实代码):
[run a fetch request] // returns 18 objects
[save context] // no NSError, returns YES - success
[run a fetch request] // returns 0 objects; request is exactly the same request as previous
如果我不保存,两个 fetch 请求都会返回 18 个对象。
获取请求是在一个单独的方法中完成的,所以我确信两次请求都是相同的。请求使用了这个 NSPredicate:
NSPredicate *predicateFailsAfterSave = [NSPredicate predicateWithFormat:@"NOT (%@ IN games)", self.game]; // where THISGAME is not IN self.games
如果我将此谓词更改为更简单的东西,例如“fullName CONTAINS %@”、@“Frank”,那么即使我包含了 save 命令,它也可以两次工作。该谓词应返回尚未分配给 self.Game 对象的所有客人。它第一次工作,然后如果我保存则返回 0。
模型,由两个实体组成:
“客人”,实体。 1个属性(全名,字符串); 1 关系(对许多人;“游戏”,与被称为“客人”的游戏相反)
“游戏”,实体。 0 属性。 1 关系(对许多人;“客人”,与客人相反,称为“游戏”)
流程:
-
来宾对象是通过在视图加载时解析文本文件来创建的。 “fullName”值已设置。
NSArray *namesArray = // 这是一个字符串数组
for (NSString *playerName in namesArray) { NSManagedObject *newPlayer = [NSEntityDescription insertNewObjectForEntityForName:@"Guest" inManagedObjectContext:self.managedObjectContext]; [newPlayer setValue:playerName forKey:@"fullName"]; NSLog(@"Created %@", [newPlayer valueForKey:@"fullName"]); } -
在制作来宾对象时,游戏对象还没有被实例化。 (对于整个问题,不存在设置 Game 和 Guest 之间关系的情况。)然后创建 Game 对象,此时它的 Guest 关系中没有对象:
-(void)viewWillAppear:(BOOL)animated { [超级viewWillAppear:动画];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mocChanged:) name:NSManagedObjectContextObjectsDidChangeNotification object:nil]; _game = [NSEntityDescription insertNewObjectForEntityForName:@"Game" inManagedObjectContext:self.managedObjectContext]; // testing [self testFetch]; /// try save NSError *error = nil; if ([self.managedObjectContext save:&error] == NO) { NSLog(@"Error: %s: %@", __PRETTY_FUNCTION__, error.localizedDescription); } // re-do fetch [self testFetch]; } -(void)mocChanged:(NSNotification *)notification { NSLog(@"notif: %@", notification.userInfo); } -
您可以看到我发送了两次 testFetch 消息,其中“保存”在它们之间。如果我注释掉保存,它们都会返回相同的结果。添加保存,后者返回0个对象。这里是 testFetch:
-(void)testFetch { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Guest"]; NSPredicate *testKnownGoodPredicate = [NSPredicate predicateWithFormat:@"fullName CONTAINS[cd] %@", @"wood"]; NSPredicate *predicateFailsAfterSave = [NSPredicate predicateWithFormat:@"NOT (%@ IN games)", self.game]; // where THISGAME is not IN self.games request.predicate = predicateFailsAfterSave; NSError *error = nil; NSArray *guestsNotCheckedInArray = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; if (guestsNotCheckedInArray == nil) { NSLog(@"Error initializing GuestsNotCheckedIn %s: %@", __PRETTY_FUNCTION__, error.localizedDescription); } NSLog(@"GuestsNoCheckedIn (game: %p; context:%p): %lu", self.game, self.managedObjectContext, (long)guestsNotCheckedInArray.count); }
前面代码的输出:
GuestsNoCheckedIn(游戏:0x10b54aeb0;上下文:0x10b526840):18
通知:{ 插入 = "{(\n (实体: 游戏; id: 0x10b54af10 ;数据: {\n 客人 = (\n );\n})\n)}"; managedObjectContext = ""; }
GuestsNoChecked In(游戏:0x10b54aeb0;上下文:0x10b526840):0
预期输出:
GuestsNoCheckedIn ...:两次都是 18。
我一直在研究三种理论:
- 保存期间关系受到影响。
- 谓词中有问题导致它再次失败。
- 获取对象时,它们的关系被意外更改。
为了帮助测试这些理论,我已经:
- 从项目中删除了 NSManagedObject 子类。这向我保证没有可能破坏关系的 -awakeFrom*。
- 从模型中删除了所有其他实体。
- 已注册接收 NSManagedObjectContextObjectsDidChangeNotification 通知,因此我可以查看是否发生了我未预料到的变化。
- 我已经比较了 MOC 和 Game 对象的地址,以确保我没有意外创建另一个。
这让我觉得问题出在谓词上,而不是保存上。虽然我有点茫然。
有什么想法吗?
【问题讨论】:
标签: ios objective-c core-data