首页 > 解决方案 > 从选取器返回的 SwiftUI 核心数据对象

问题描述

我有两个核心数据实体(在 中CloudKit),它们之间有关系。在更新一个实体时,我试图通过选择器添加用户选择的结果来添加相关实体。

我面临的问题是我无法让选择器将记录作为选择返回 - 它始终为空。我开发了以下测试代码来突出显示特定案例。选择器填充,我可以让它返回实际记录以外的任何内容 - 但要插入关系,我需要记录本身。这是选择器测试代码。选择总是空的。

我会很感激方向。

struct TestView: View {
    
    @Environment(\.managedObjectContext) var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Player.familyName, ascending: true)],
        animation: .default)
    private var players: FetchedResults<Player>
    
    @State var selection: Player?
    
    var body: some View {
        VStack{
            Picker("", selection: $selection){
                ForEach(players, id: \.self){ (player: Player) in
                    Text(player.givenName!).tag(player.self)
                }
            }
            Text(((selection?.familyName ?? "default")))
            Text("\(players.count)")
        }
    }
}

Player 实体如下所示:

在此处输入图像描述

标签: core-dataswiftui

解决方案


Apple 论坛上一位乐于助人的评论者向我展示了答案——这与确保选择变量不是可选的有关:

import SwiftUI
import CoreData
struct ContentView: View {
    @FetchRequest private var players: FetchedResults<Player>
    @State private var selection: Player
    init(moc: NSManagedObjectContext) {
        let fetchRequest: NSFetchRequest<Player> = Player.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Player.familyName, ascending: true)]
        fetchRequest.predicate = NSPredicate(value: true)
        self._players = FetchRequest(fetchRequest: fetchRequest)
        do {
            let firstPlayer = try moc.fetch(fetchRequest)
            self._selection = State(initialValue: firstPlayer[0])
        } catch {
            fatalError("Uh, fetch problem...")
        }
    }
    var body: some View {
        VStack{
            Picker("", selection: $selection){
                ForEach(players) { (player: Player) in
                    Text(player.givenName ?? "")
                        .tag(player)
                }
            }
            Text(selection.familyName ?? "No family name")
            Text("\(players.count)")
        }
    }
}

推荐阅读