Objective-C/iOS:如何从 CoreData 中的属性中删除“值”?

Posted

技术标签:

【中文标题】Objective-C/iOS:如何从 CoreData 中的属性中删除“值”?【英文标题】:Objective-C/iOS: How to remove 'values' from an attribute in CoreData? 【发布时间】:2012-07-10 02:36:22 【问题描述】:

objective-c 非常新,CoreData 非常新 - 这个问题感觉非常简单,但尽管搜索了 1.5 小时,我还是无法弄清楚!寻找更伟大的思想。

情况:CoreData 中有一个实体(“AssetType”),该实体有一个属性(“标签”)。 AssetType 与另一个实体(“项目”)具有 对多 关系。 Items 与 AssetType 具有 一对一 的关系,“label”目前有 3 个可能的值 - “Electronics”、“Furniture”、“Jewelry”。

目标: 非常简单,我想从所有对象中删除其中一个值。我更希望这一切一次性完成,而不是通过“许多”对象(eww)上的 for 循环,但说实话,我只是迷失在 CoreData 和语法中,所以无论你能提供什么都很棒。

代码结构/背景:如果需要,我可以粘贴更多内容,但我使用通用 UITableView + UINavigationItem editButtonItem 来执行编辑(如果重要,在 UIPopoverController 内) - 这就是删除的地方方法来自 - 我通过 tableView:commitEditingStyle:forRowAtIndexPath: delegate/protocol 方法捕获它。这部分不是问题——我知道把代码放在哪里,我只是迷失在 CoreData 中。 :(

twist: AssetType 目前没有一个类 - 它纯粹作为 Item 类中的一个属性(以及 CoreData 中的一个单独实体)存在,到目前为止一直很好.. 但也许当我需要操作属性时(例如删除它们!),这是我需要引入自己的类的时候吗?希望不是这样。

谢谢大家!

【问题讨论】:

【参考方案1】:

或者,如果您真的想完全删除 AssetType,您可以在模型中设置删除规则,以将反向关系从 AssetType 返回到 Item。在这种情况下,听起来你想要一个Nullify 规则,

然后您只需删除有问题的AssetType 对象,然后在下次保存时自动取消来自Items 的所有链接,这些链接具有AssetType

// Get descriptions of our entities so we can create some.
NSEntityDescription *assetTypeEntityDescription = [NSEntityDescription entityForName:@"AssetType" inManagedObjectContext:self.managedObjectContext];
NSEntityDescription *itemEntityDescription = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.managedObjectContext];

// Create some asset types
AssetType *furnitureAssetType = [[AssetType alloc] initWithEntity:assetTypeEntityDescription insertIntoManagedObjectContext:self.managedObjectContext];
AssetType *electronicsAssetType = [[AssetType alloc] initWithEntity:assetTypeEntityDescription insertIntoManagedObjectContext:self.managedObjectContext];
AssetType *jewelryAssetType = [[AssetType alloc] initWithEntity:assetTypeEntityDescription insertIntoManagedObjectContext:self.managedObjectContext];

furnitureAssetType.label = @"Furniture";
electronicsAssetType.label = @"Electronics";
jewelryAssetType.label = @"Jewelry";

// Create some items
Item *item1 = [[Item alloc] initWithEntity:itemEntityDescription insertIntoManagedObjectContext:self.managedObjectContext];
item1.assetType = furnitureAssetType;

Item *item2 = [[Item alloc] initWithEntity:itemEntityDescription insertIntoManagedObjectContext:self.managedObjectContext];
item2.assetType = electronicsAssetType;

Item *item3 = [[Item alloc] initWithEntity:itemEntityDescription insertIntoManagedObjectContext:self.managedObjectContext];
item3.assetType = jewelryAssetType;

[self.managedObjectContext save:nil];

NSLog(@"item1 asset type is:%@", item1.assetType.label);
// Output: item1 asset type is:Furniture

// Delete the furniture asset type
[self.managedObjectContext deleteObject:furnitureAssetType];

NSLog(@"item1 asset type is:%@", item1.assetType.label);
// Output: item1 asset type is:Furniture

// Save the changes..
[self.managedObjectContext save:nil];    

NSLog(@"item1 asset type is:%@", item1.assetType.label);
// Output: item1 asset type is:(null)
// Because of the delete rule when the furniture object is deleted relationships that pointed to it are nulled out.  
// The furniture asset type no longer exists.  
// There are now only 2 asset types in the persistent store.

【讨论】:

感谢 rory - 所以听起来我会创建一个 NSEntityDescription 实体(在我的情况下为 AssetType),然后为同一实体(AssetType)设置一个 NSRelationshipDescription,然后删除关联的值之一带有“标签”属性..但是我如何首先删除该值(例如“家具”)?不幸的是,我被困在这个过程的非常基础上。 :) 我添加了示例代码和模型来说明这一点。在此示例中,我使用模型编辑器(推荐!)构建了模型,并从模型 Editor->Create NSManagedObject Subclass.. 生成了子类,因此我可以使用属性和类型名称等。 至于你添加的扭曲。假设您的意思是您有一个 AssetType 实体,但您只是在用户选择它时从中获取标签文本并将其设置为 Item? 上的字符串属性,那么是的,您需要一个正确的关系,如上图所示利用此处显示的核心数据的自动功能以及 Tommy 的替代方法(实现类似结果但不会删除 AssetType 谢谢,罗里,这很有帮助。问题:目前,我只在didEnterBackground 上存钱——我需要在我的申请中包含更多的存钱吗?还是 CoreData 允许我在内存中处理这个 - 例如如果我使用上述方法删除标签,我是否可以使用deleteRowsAtIndexPaths:withRowAnimation: 重新绘制 UITableView?即如果我有 6 个 AssetType,然后使用上面的方法删除一个,表格会知道现在只有 5 个吗?我假设是的,因为我现在甚至可以在不执行 CoreData 保存的情况下添加标签。 (对于它的价值,在没有专用 AssetType 类的情况下使用您的方法实际上将一直有效,直到在 deleteRowsAtIndexPaths:withRowAnimation: 期间重新绘制表格 - 那时,如果我要求所有的标签,它会全部返回它们(例如,我有 5 个这样列出的项目:(entity: AssetType id: ... ; data: \n items = \"<relationship fault: ...>\";\n label = Furniture;\n)),除了已删除的仍然存在但读取 (entity: AssetType; id: ... ... ; data: <fault>)(请注意数据在我删除的项目中完全是【参考方案2】:

明确一点:您有两个实体,“资产类型”和“项目”,它们具有多对多关系。您希望所有项目同时切断与特定资产类型的连接,理想情况下,您不希望遍历项目。我收到了吗?

如果您的资产类型确实是独一无二的(例如,恰好有一个带有“家具”标签),那么您可以直接取消链接——Core Data 中的关系始终是双向的,从一侧取消链接会自动取消链接从另一个。 NSManagedObject 子类还具有访问器,可以在集合中的“对多”关系的末尾添加或删除事物。所以例如

[furnitureObject removeItems:furnitureObject.items];

这是假设您的资产类型实体有一个名为“items”的“to many”连接,该连接链接到项目。

否则,您可以运行谓词来获取字符串名称为“Furniture”的所有资产的列表并遍历这些资产,我猜。

【讨论】:

谢谢 Tommy - 你明白了,除了 Items 与 Asset Type 是 to-one 关系(Items 只能有一个 Asset Type),但 Asset Types 是许多(我可能有 5 个不同的项目,它们都是“计算机”资产类型)。这会改变解决方案吗? 不应该,除非目标是删除具有某种资产类型的所有项目,而不仅仅是切断与该资产类型的链接? nope - 目标只是完全删除 AssetType(这样在为 Item #1 设置 AssetType 时,如果您删除 Asset Type #6,它会为所有 Item 删除并删除)。我无法使上述方法正常工作(编译器错误)..我会继续寻找。什么代码 sn-ps 将有助于更清楚地概述我正在发生的事情?这感觉就像它涉及很多代码,所以我不想粘贴到我的整个项目中。 ;) 我还在上方添加了一个“扭曲”,概述了我昨晚忘记的一个细节——以防万一

以上是关于Objective-C/iOS:如何从 CoreData 中的属性中删除“值”?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Objective-C iOS 中解析 JSON

Objective-C iOS 从 Torrent 文件生成 Info_Hash

如何在objective-c ios中等待完成块完成[重复]

qt5cored.dll丢失怎么解决

如何停止 GCDWebUploader 的实例 - Objective-c iOS

Objective-c (iOS) 中常见的 HTTP 请求委托模式