【问题标题】:Swift NSManagedObject factorySwift NSManagedObject 工厂
【发布时间】:2015-08-05 03:32:03
【问题描述】:

我是 Swift 2.0 的新手,也是 Core Data 的新手。

我正在寻找“取消扁平化”各种核心数据NSManagedObjects。现在,我正在使用谓词并加入属性“parentNameID”和“nameID”。我确实在 Core Data GUI 中设置了 itemCategory 和 itemCategoryChildren 关系,我想继续加入这种关系,而不是通过 parentNameID>nameID 和谓词进行“平面”连接。我怀疑我真的很近,但我的 fetchedResultsParentID 容器总是空的。

请不要引导我使用 SuperAwesomeAPI 或 StudlyGreatAPI;我希望通过本机核心数据调用来做到这一点。我看到本来可以很有价值的讨论被随便提及使用的外部 API 所扼杀。

我正在尝试将我的一个类与工厂方法--enumerate()--转换为核心数据enumerate() 调用按预期工作——返回一个类对象数组——当我的类属于 NSObject 时——但我似乎无法将 NSManagedObjects 的分类“展开”成一个完整的核心数据关系。

我有什么:一个项目类(NSObject)和一个工厂类函数enumerate(),它返回一个项目数组。

我想要什么: 一个 Items 类 (NSManagedObject) 和一个返回 NSManagedObjects 的工厂类函数 enumerate()。

我做了什么:enumerate() 中设置了项目属性,并生成了这些项目的数组。我在外部调用enumerate(),来自AppDelegate.Swift 文件:var items = Item.enumerate(),然后通过setValue() 在NSManagedObject 上设置属性。

我查看了各种各样的答案,我真正能找到的关于工厂和核心数据的唯一内容是this post

我当然不会从 JSON 或 XML 文件中获取这些项目,并且将来可能会采用这种方式,但这似乎比创建数组的工厂类更难。如果没有,请告诉我!!

相关AppDelegate.Swift函数:

func preloadData(EntityName: String) {
    // Remove any data that may exist
    removeData(EntityName)

    var items = AllItems.enumerate()

    print("Array enumerated with \(items.count) items.")

    for item in items {
        let newItem = NSEntityDescription.insertNewObjectForEntityForName(EntityName, inManagedObjectContext: managedObjectContext) as NSManagedObject
        // Required
        newItem.setValue(item.isCategory, forKey: "isCategory")
        newItem.setValue(item.name, forKey: "name")
        newItem.setValue(item.shortDetail, forKey: "shortDetail")
        newItem.setValue(item.itemID, forKey: "itemID")

        if (item.parentItemID != nil) {
            let fetchRequestParentID = NSFetchRequest(entityName:EntityName)
            let predicateParentID = NSPredicate(format: "parentItemID == %i", item.parentItemID!)
            fetchRequestParentID.predicate = predicateParentID
            do {
                let fetchedResultsParentID = try managedObjectContext.executeFetchRequest(fetchRequestParentID) as? [NSManagedObject]
                // success ...
                // THIS IS WHERE THINGS FAIL.
                //                    newItem.setValue(fetchedResultsParentID, forKey: "itemCategory")
                newItem.setValue(fetchedResultsParentID, forKeyPath: "itemCategory")
            } catch let error as NSError {
                // failure
                print("Fetch failed: \(error.localizedDescription)")
            }

                //                let fetchRequestParentID = NSFetchRequest(entityName: EntityName)
                //                fetchRequestParentID.fetchLimit = 1
                //                
                //                let fetchedEntitiesParentID = self.managedObjectContext.executeFetchRequest(fetchRequestParentID)
                //                
                //                newItem.setValue(newItem, forKey: "itemCategory")
        }
    }

    items.removeAll()

    do {
        try managedObjectContext.save()
    } catch let error as NSError {
        print("Failed: \(error.localizedDescription)")
    }
}

【问题讨论】:

    标签: ios core-data swift2


    【解决方案1】:

    我假设 itemCategory 关系是自反的,即从你的实体到它自己,itemCategoryChildren 是它的逆关系,并且它是多对一的(每个对象只有一个 itemCategory,但可以有许多itemCategoryChildren)。

    您的谓词似乎正在尝试使用与您的newItemparentItemID 匹配的parentItemID 获取项目。但是

    a) 你从来没有设置parentItemID 属性,所以什么都不会匹​​配;因此你的结果是空的。

    b) 我怀疑您实际上想要获取与 itemID 匹配的项目 parentItemID (..."a 'flat' join via parentNameID>nameID"):

    let predicateParentID = NSPredicate(format: "itemID == %i", item.parentItemID!)
    

    c) 获取的结果将是一个数组,所以在设置关系时需要从数组中提取项目:

    let parentItem = fetchedResultsParentID[0]
    newItem.setValue(parentItem, forKeyPath: "itemCategory")
    

    (另请注意,在设置关系时,您使用的是 NSManagedObject 本身,而不是关联的 ID)。

    d) 另一个问题是您可能会先加载子项,然后再加载其父项。所以实际上加载所有项目可能会更好,然后迭代并建立关系。

    【讨论】:

    • 你好。我只是回到这个话题。感谢您花时间回答!有几件事要开始:(b)是绝对正确的。我已经习惯了 RDBMS 的工作,所以我在这里构建的是一个使用节点数组的双向链表。相应地,您是对的:每个节点都有您描述的关系设置。 (d) 是一个好点;我的工厂类对加载顺序很精确,但我开始怀疑我是否必须先创建一堆 NSManagedObject 节点,然后建立它们的关系。我会让你知道(a)和(c)!我会回来的。
    • 嗯。我记得昨晚看到这个错误。 let parentItem = fetchedResultsParentID[0] 产生失败“结果类型'元素'与预期类型不匹配。” 我知道互联网上的事情可能会悄然消亡,所以我想特别回来感谢您。 我阅读了一些关于 NSSet 的信息。这让我看到可以通过.allObjects 进行 NSSet->Array 转换。对于其他苦苦挣扎的人,这是我的 viewController 中的一个示例:items = parentItem!.valueForKeyPath("itemCategoryChildren")?.allObjects as! [Item]
    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    相关资源
    最近更新 更多