这里是 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)
]
}
}
感谢任何可以帮助我的人!
该错误包含一条非常重要的信息:
包装的值必须是一个对象
您需要
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 }
}