【问题标题】:Objective-C/iOS: How to remove 'values' from an attribute in CoreData?Objective-C/iOS:如何从 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 中的一个单独实体)存在,到目前为止一直很好.. 但也许当我需要操作属性时(例如删除它们!),这是我需要引入自己的类的时候吗?希望不是这样。

谢谢大家!

【问题讨论】:

    标签: objective-c ios ios5 core-data ios5.1


    【解决方案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 将有助于更清楚地概述我正在发生的事情?这感觉就像它涉及很多代码,所以我不想粘贴到我的整个项目中。 ;)
    • 我还在上方添加了一个“扭曲”,概述了我昨晚忘记的一个细节——以防万一
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 2022-09-30
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    相关资源
    最近更新 更多