我可以将泛型类型作为 @Bindable 传递到 SwiftUI 视图中吗?

问题描述 投票:0回答:1

这里是 Swift 新手,请多多指教! 如何将此 SwiftUI 视图转换为接受不同类型项目作为输入的版本?

我的 iOS 应用程序中有此视图:

struct EditMeshType: View {
    
    @Bindable var item: MeshType
    private let navTitle: String = "Edit Mesh Types"
    var body: some View {
        Form {
            TextField("Name", text: $item.name)
            Toggle("Active?", isOn: $item.activeFlag)
        }
        .navigationTitle(navTitle)
        .navigationBarTitleDisplayMode(.inline)
    }
}

此视图是从另一个视图调用的,我传入“MeshType”类型的特定“项目”以允许用户更改名称或活动标志。主视图使用SwiftData, “item”是 MeshType 数组的成员,它是 @Query 声明的一部分。我已粘贴到下面的 MeshType 对象中。

我想将 MeshType 以外的类型传递给该视图。例如,我有另一种名为 ArtifactType 的类型,它也具有“name”和“activeFlag”属性。 我有很多属性都遵循这种模式。如果我可以创建一个通用视图,我不想为每个视图创建单独的视图。这是一个简化的示例,但是 希望这足以说明我有理由不想将这些(相似但不相同)查找组合到具有“类型”分类器的单个类中。

我试过这个:

struct EditLookup<T>: View {
    
    @Bindable var item: T
    private let navTitle: String = "Edit Lookup Value"
    var body: some View {
        Form {
            TextField("Name", text: $item.name)
            Toggle("Active?", isOn: $item.activeFlag)
        }
        .navigationTitle(navTitle)
        .navigationBarTitleDisplayMode(.inline)
    }
}

但是 @Bindable 行给出了编译器错误: “'init(wrappedValue:)'不可用:包装值必须是符合Observable的对象”

这让我很困惑,因为 MeshType 使用 @Model 宏,我认为这让我符合 Observable。不知怎的,通用版本不知道无论什么类型 T 符合 Observable。

然后我尝试引用 T 的协议:

protocol Lookup: Observable {
    var name: String { get set }
    var sortOrder: Int { get set }
    var metaCreateDate: Date { get set }
    var activeFlag: Bool { get set }
    var preventDelete: Bool { get }
    var logentries: [LogEntry]? { get }
}

并使我的 MeshType 模型类型符合此协议,然后编辑我的通用视图以引用该协议作为约束:

struct EditLookup<T: Lookup>: View {
    
    @Bindable var item: T
    private let navTitle: String = "Edit Lookup Value"
    var body: some View {
        Form {
            TextField("Name", text: $item.name)
            Toggle("Active?", isOn: $item.activeFlag)
        }
        .navigationTitle(navTitle)
        .navigationBarTitleDisplayMode(.inline)
    }
}

但这在编译器中给了我同样的错误。

我的做法是错误的吗?有没有更好的方法来实现我的目标(将各种类型传递到通用编辑视图?)

这是我的 MeshType 模型。 MeshType 是 LogEntry 上的众多“查找”字段之一。其他查找字段具有类似的结构,并且都符合 Lookup。

@Model
class MeshType: Lookup {
    var name: String
    var sortOrder: Int
    var metaCreateDate: Date
    var activeFlag: Bool
    
    @Relationship(inverse: \LogEntry.meshType)
    var logentries: [LogEntry]?
    
    var preventDelete: Bool {
        logentries?.count ?? 0 > 0
    }
    
    init(name: String, sortOrder: Int = 0) {
        self.name = name
        self.sortOrder = sortOrder
        self.metaCreateDate = Date.now
        self.activeFlag = true
    }
    static var sample: [MeshType] {
        [
            .init(name: "Window Screen", sortOrder: 1),
            .init(name: "Hardware Cloth", sortOrder: 2)
        ]
    }
}

感谢任何可以帮助我的人!

ios swift generics swiftui parametric-polymorphism
1个回答
0
投票

该错误包含一条非常重要的信息:

包装的值必须是一个对象

您需要

Lookup
才能符合
AnyObject
,因为
@Bindable
需要上课。我很惊讶
Observable
协议还没有这样做。

protocol Lookup: Observable, AnyObject {
    var name: String { get set }
    var sortOrder: Int { get set }
    var metaCreateDate: Date { get set }
    var activeFlag: Bool { get set }
    var preventDelete: Bool { get }
}
© www.soinside.com 2019 - 2024. All rights reserved.