【问题标题】:Creating Core Data Entity working but fetching an Entity doesn't work创建核心数据实体工作但获取实体不起作用
【发布时间】:2013-10-31 15:14:08
【问题描述】:

所以,我有一个`NSManagedObject 的用户、边界和预设。预设始终与单个用户相关联。一个用户可以有许多预设。每个预设都可以绑定一个边界。

基本上,用户有一个预设,他可以保存到他拥有的每个边界。

用户与预设有一对多的关系。 Boundary 与 Preset 是多对多的关系。

我正在尝试生成用户拥有的预设列表减去已绑定到边界的预设列表。

我正在使用魔法唱片。

我的问题是当我创建一个新的用户和边界时,这有效:

Boundary *boundary = [Boundary MR_createEntity];
boundary.name = @"test boundary";

UserDB *user = [UserDB MR_createEntity];
user.username = @"test User";

Preset *preset01 = [Preset MR_findFirstByAttribute:@"nameDisplay" withValue:@"C4"];
DLog(@"preset01.nameDisplay: %@", preset01.nameDisplay);
Preset *preset02 = [Preset MR_findFirstByAttribute:@"nameDisplay" withValue:@"B"];
DLog(@"preset02.nameDisplay: %@", preset02.nameDisplay);

[boundary setPresets:[NSSet setWithObject:preset01]];
[user setPresets:[NSSet setWithObjects:preset01, preset02, nil]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@ AND boundary != %@", user, boundary];

NSArray *presetsList = [Preset MR_findAllWithPredicate:predicate];

DLog(@"presetsList: %@", presetsList);

所以我将 preset01 设置为边界。我为用户设置了 preset01 和 preset02。所以我需要一个向用户显示 preset02 的列表(因为 preset01 已经绑定到边界,用户应该无法再次添加它)。

DEBUG | -[LoginViewController viewDidLoad] | preset01.nameDisplay: C4
DEBUG | -[LoginViewController viewDidLoad] | preset02.nameDisplay: B
DEBUG | -[LoginViewController viewDidLoad] | presetList: (
    "<SoilTestPointPreset: 0x1e06b8b0> (entity: Preset; id: 0x1e06bca0 <x-coredata://7476DB86-AF79-445C-B3AE-6C91088704A0/Preset/p98> ; data: {\n    attributes = \"<relationship fault: 0x1e074000 'attributes'>\";\n    boundary = nil;\n    gpsLocation = nil;\n    nameDisplay = B;\n    nameTitle = nil;\n    rgbColor = \"0x1e06b1d0 <x-coredata://7476DB86-AF79-445C-B3AE-6C91088704A0/RGBColor/p49>\";\n    testing = nil;\n    user = \"0x1e05ff60 <x-coredata:///UserDB/t59757D99-2FBF-4FBF-97AF-39582FC4B5503>\";\n})"

)

这正是我所期望的。但是现在当我获取 User 和 Boundary 对象时:

Boundary *boundary = [Boundary MR_findFirstByAttribute:@"boundaryID" withValue:@3748];
DLog(@"boundary.name: %@", boundary.name);

UserDB *user = [UserDB MR_findFirstByAttribute:@"uid" withValue:@99];
DLog(@"user.username: %@", user.username);

我的数组是空的:

DEBUG | -[LoginViewController viewDidLoad] | boundary.name: 997677
DEBUG | -[LoginViewController viewDidLoad] | user.username: thatPerson
DEBUG | -[LoginViewController viewDidLoad] | preset01.nameDisplay: C4
DEBUG | -[LoginViewController viewDidLoad] | preset02.nameDisplay: B
DEBUG | -[LoginViewController viewDidLoad] | presetList: (
)

为什么从 Core Data 获取用户和边界会改变结果而不是创建结果?

更新:

我补充说:

Boundary *boundary = [Boundary MR_findFirstByAttribute:@"boundaryID" withValue:@3748];
DLog(@"boundary.name: %@", boundary.name);
DLog(@"boundary.presets.count: %d", boundary.presets.count); // Added

UserDB *user = [UserDB MR_findFirstByAttribute:AVI_UID withValue:@99];
DLog(@"user.username: %@", user.username);
DLog(@"user.presets.count: %d", user.presets.count); // Added

DLog(@"AFTER | boundary.presets.count: %d", boundary.presets.count); //Added
DLog(@"AFTER | user.presets.count: %d", user.presets.count); //Added

[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait]; //Added

它们的用户和边界具有预设关系:

DEBUG | -[LoginViewController viewDidLoad] | boundary.name: 997677
DEBUG | -[LoginViewController viewDidLoad] | BEFORE | boundary.presets.count: 0
DEBUG | -[LoginViewController viewDidLoad] | user.username: iDealer
DEBUG | -[LoginViewController viewDidLoad] | BEFORE | user.presets.count: 0
DEBUG | -[LoginViewController viewDidLoad] | preset01.nameDisplay: C4
DEBUG | -[LoginViewController viewDidLoad] | preset02.nameDisplay: B
DEBUG | -[LoginViewController viewDidLoad] | AFTER | boundary.presets.count: 1
DEBUG | -[LoginViewController viewDidLoad] | AFTER | user.presets.count: 2
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x20831a80) → Saving <NSManagedObjectContext (0x20831a80): *** DEFAULT ***> on *** MAIN THREAD ***
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x20831a80) → Save Parents? 1
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x20831a80) → Save Synchronously? 1
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x1f59e860) → Saving <NSManagedObjectContext (0x1f59e860): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x1f59e860) → Save Parents? 0
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x1f59e860) → Save Synchronously? 1
__70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x1f59e860) → Finished saving: <NSManagedObjectContext (0x1f59e860): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
DEBUG | -[LoginViewController viewDidLoad] | presetList: (
)

【问题讨论】:

  • 我认为问题在于我的NSPredicte,我认为AND boundary != %@ 的行为不像我认为的那样。

标签: ios objective-c core-data magicalrecord


【解决方案1】:

您需要先保存数据,然后才能从商店获取数据。使用 MR_saveToPersistentStoreAndWait 或其他变体。获取总是“磁盘”,所以首先保存应该可以解决这个问题。

【讨论】:

  • 上下文不是商店的副本吗?您在该上下文中所做的任何更改都会保存在该上下文中。因此,如果您获取该上下文,您会获得新的更改吗?它基本上是当地的临时商店?如果需要持久化(在应用会话之间保存数据),则需要将 保存到持久化存储中。
  • 我认为您并不完全了解这些部分是如何协同工作的。我强烈建议重新阅读核心数据文档并了解核心数据堆栈的工作原理。上下文不是商店。商店不是上下文。如果您需要临时数据存储,我建议您查看内存存储详细信息。
  • 我在松散地使用术语库。该商店用于永久(又名,在应用程序会话之间)。上下文与存储中的所有实体一起加载并临时维护它们,直到上下文被丢弃或其更改被保存回存储。因此,您可以在上下文中获取某些内容、更改、重新获取它,它将反映您刚刚所做的更改(只要它们都在同一上下文中完成)。如果您在不同的上下文中获取相同的实体,您所做的更改将不会发生。
【解决方案2】:

在玩了一堆之后,我将问题缩小到我正在使用的NSPredicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@ AND boundary != %@", user, boundary];

查询中的NOTNONE 似乎存在问题。在我发布的另一个问题中得到了答案:NSPredicate with a !=?

答案涉及使用SUBQUERY 而不是NOT

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@ AND SUBQUERY(boundary, $p, $p == %@).@count == 0", user, boundary];

我猜我所做的提取是好的,由于NSPredicate 不好,它会返回 0,但我没有肯定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多