【问题标题】:Core Data, Relationship - store multiple selected rows to entity核心数据,关系 - 将多个选定的行存储到实体
【发布时间】:2018-07-09 10:48:16
【问题描述】:

我需要帮助 - 我想通过关系将 tableView 中的多个选定行存储到一个实体中)

假设我有这个: 核心数据模型: Entity_1 = 包 Entity_2 = 物品

用户可以为洞家庭创建“Bagmanymaby 袋子”和他想要放入 selectet 袋子的“物品”。因此,如果家庭去度假,每个家庭成员都有自己的袋子,里面有一些物品。有些物品会在每个“包”中(如果用户选择它们。)

Bags (for):
- Carol 
- Bens 
- Eva

Items:
- toothbrush
- towel
- shoes
- hairbrush
- makeup

--> 我知道只将一个项目存储到每个实体中的方法(通过关系)。但我需要帮助在选定的“包”中一次存储多个项目

本只想拿起:牙刷和毛巾 Carol 拿起所有 5 件物品 Eva 选择牙刷、化妆品和鞋子

如果我打开 tableViewController 列出所有项目: 我必须将所有选定的项目存储到一个数组中,然后将该数组存储到 coredata。谁能给我一段代码?谢谢你帮助我。

FetchesResultsController:

    lazy var fetchedResultsCtrl: NSFetchedResultsController<Item> = {
        let request: NSFetchRequest<Item> = Item.fetchRequest()
        let sort = NSSortDescriptor(key: "itemName", ascending: true)
        //let catSort = NSSortDescriptor(key: "kategorie", ascending: true)
        request.sortDescriptors = [sort]
        let fetchedCtrl = NSFetchedResultsController(fetchRequest: request, managedObjectContext: self.managedContext, sectionNameKeyPath: nil, cacheName: nil)
        // an UserDefaults binden o.ä.:
        //NSFetchedResultsController.deleteCache(withName: "kategorieCache")

        fetchedCtrl.delegate = self
        return fetchedCtrl
    }()

表格视图:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! detailsInterieur
        let items = fetchedResultsCtrl.object(at: indexPath)
        cell.nameLabel?.text = items.itemName

        if let paths = tableView.indexPathsForSelectedRows {
            if (paths.contains(indexPath)){
                cell.accessoryType = .checkmark
            }
            else {
                cell.accessoryType = .none
            }
        }
        else{
            cell.accessoryType = .none
        }
        cell.selectionStyle = .none

        return cell
    }


override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         print("select")
}


override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
         print("deselect")
}

编辑: 我可以使用以下代码找到选择:

guard let selectedRows = tableView.indexPathsForSelectedRows else {
            return
        }

这些函数是自动生成的。但是我怎样才能以正确的方式使用它们呢?

@objc(addBag_RELObject:)
@NSManaged public func addToBag_REL(_ value: MyBag)

@objc(removeBag_RELObject:)
@NSManaged public func removeFromBag_REL(_ value: MyBag)

@objc(addBag_REL:)
@NSManaged public func addToBag_REL(_ values: NSSet)

@objc(removeBag_REL:)
@NSManaged public func removeFromBag_REL(_ values: NSSet)


@objc(addItem_RELObject:)
@NSManaged public func addToItem_REL(_ value: Item)

@objc(removeItem_RELObject:)
@NSManaged public func removeFromItem_REL(_ value: Item)

@objc(addItem_REL:)
@NSManaged public func addToItem_REL(_ values: NSSet)

@objc(removeitem_REL:)
@NSManaged public func removeFromitem_REL(_ values: NSSet)

【问题讨论】:

  • 您的数据模型中是否设置了BagItem 之间的关系?如果这样做了,则只需在 Bags 对象上调用正确的方法即可,例如myBag.addToItems(myItem)
  • 嗨,是的,我做到了 - bag(to one) 和 item(to many) 之间存在关系
  • 对我来说,这听起来更像是一种多对多的关系,因为您不会为每个包创建新项目,而是在将它们添加到包时从现有项目中进行选择。无论如何只需将所有 Item 对象添加到选定的包并保存您的上下文。

标签: ios swift core-data relationship


【解决方案1】:

根据您的方案,items 应该与您的 Bag 实体之间存在to many 关系。在这种情况下,BagNSMangedObject 类或其扩展(取决于您在 codegen 中选择的内容)应该生成了一个方法 @NSManaged public func addToItems(_ values: NSSet)。 您可以从 tableView 的 var indexPathsForSelectedRows generate Items 中获取选定的项目,并通过调用 addToItems(:) 将它们添加到您的 bag 对象中。

但更好的方法是明智地使用 CoreData。在您的情况下, Item 将具有 bag 属性(根据关系),因此当您创建 item 并为其分配一个有效的 bag 对象它会自动更新关系的另一端。

【讨论】:

  • 我正在编辑我的帖子......所以我不清楚如何使用这个函数 addToItems(:) - 我见过他们,是的......但是 - 如果我理解正确,我必须通过“indexPathsForSelectedRows”将我选择的项目存储在一个数组中让 selectedRows = tableView.indexPathsForSelectedRows else { return }
  • 你的包与物品的关系应该是'to one',所以前四种方法没有意义,检查你的模型。并创建一个包管理对象,然后为您选择的每个索引路径创建一个项目对象并将包对象分配给每个项目。
  • 嗯,我认为它是多对多的?一个袋子可以装全部或几件物品,物品可以装在全部或部分袋子里。
  • 单个物品实例不能在多个包中。例如,一条毛巾不能属于两个袋子。您必须为每个袋子制作两条单独的毛巾。
  • hmmm ...但是“项目”不是这个 一条毛巾 - 我要选择的项目是,就像一个类别“毛巾” - 所以在 ech 包中必须是一条毛巾 - 不是这个显式毛巾这样的毛巾。
【解决方案2】:

鉴于您在selectedRow 中选择了上述项目,并且您对当前选择的包有一些属性,比如说selectedBag 然后做

guard let selectedRows = tableView.indexPathsForSelectedRows else {
    return
} 

for path in selectedRows {
    let item = fetchedResultsCtrl.object(at: path.row)
    selectedBag.addToItem_REL(item)
}

然后在您的托管对象上下文中调用save()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多