SwiftUI 通用数组模型
Posted
技术标签:
【中文标题】SwiftUI 通用数组模型【英文标题】:SwiftUI Generic Array Model 【发布时间】:2021-07-25 22:32:08 【问题描述】:我有一个 Binding 变量,我正在尝试将其设为 Generi Array。我将在其中采用两个不同的模型,并且我想达到模型中的图像属性。我该怎么做?
我在不同的页面转换中使用了两种不同的模型。 如何使保存模型的数组通用?
模型 1
struct PoliceSignContainer: Codable, Hashable
var policeQuestions: [PoliceSign]?
enum PoliceSignSectionType: String, Codable, Hashable
case A = "A"
case B = "B"
case C = "C"
struct PoliceSign: Codable, Hashable
var id: Int?
var image: String?
var sections: [PoliceSignSectionType.RawValue : String]?
var correct: String?
模型 2
struct TrafficSignContainer: Codable, Hashable
var trafficQuestions: [TrafficSign]?
enum TrafficSignSectionType: String, Codable, Hashable
case A = "A"
case B = "B"
struct TrafficSign: Codable, Hashable
var id: Int?
var image: String?
var sections: [TrafficSignSectionType.RawValue : String]?
var correct: String?
struct QuestionCardView: View
@EnvironmentObject var optionConfigure: OptionConfigure
@Binding var questions: [Any]
var body: some View
VStack
....
ZStack
ForEach((questions.indices).reversed(), id: \.self) index -> AnyView in
let relativeIndex = index - optionConfigure.step
switch relativeIndex
case 0...2:
return AnyView(
ImageCard(image: .constant("\(questions[index].image ?? "p1")")) // here
...
)
default:
return AnyView(EmptyView())
.animation(.spring())
OptionView()
...
【问题讨论】:
这能回答你的问题吗? Is it possible to make SwiftUI ListMenu with different behaviors? 您是指同时有两个不同的模型(异构集合),还是视图的每个实例都为数组采用一种类型? @jnpdx 不能同时使用两个模型。 【参考方案1】:为了使您的 Binding 数组又名问题变得通用,您只需符合 Hashable,访问符合 CustomStringConvertible 的字符串即可。查看示例代码:
struct QuestionCardView<T: Hashable & CustomStringConvertible>: View
@EnvironmentObject var optionConfigure: OptionConfigure
@Binding var questions: [T]
var body: some View
Text("")
VStack
....
ZStack
ForEach((questions.indices).reversed(), id: \.self) index -> AnyView in
let relativeIndex = index - optionConfigure.step
switch relativeIndex
case 0...2:
return AnyView(
ImageCard(image: String(describing: questions[index].image) ?? "p1")")) // here
...
)
default:
return AnyView(EmptyView())
.animation(.spring())
OptionView()
...
工作示例:
struct ContentView: View
@State private var array: [String] = [ "applelogo", "alarm", "person.fill.questionmark", "cloud.drizzle.fill", "swift"]
var body: some View
CustomView(array: $array)
struct CustomView<T: Hashable & CustomStringConvertible>: View
@Binding var array: [T]
var body: some View
VStack
ForEach(array, id:\.self) item in
ImageView(imageString: String(describing: item))
struct ImageView: View
let imageString: String
var body: some View
Image(systemName: imageString)
.resizable()
.scaledToFit()
.frame(width: 50, height: 50, alignment: Alignment.center)
【讨论】:
单独设置Hashable
不允许访问以ImageCard
开头的行上的image
属性
是的,它也需要符合CustomStringConvertible
。
CustomStringConvertable
没有 image
属性。
都可以看例子! @UfukKöşker:我无权访问您的项目,我无法以这种方式帮助您,请查看示例并采纳想法。
我现在明白了。我会再试试你的代码。【参考方案2】:
这是一个基本示例,显示了一个对 @Binding
数组有一般要求的视图,就像你有的那样:
enum TrafficSignSectionType: String, Codable, Hashable
case A = "A"
case B = "B"
struct TrafficSign: Codable, Hashable, Question //<-- Here
var id: Int?
var image: String?
var sections: [TrafficSignSectionType.RawValue : String]?
var correct: String?
enum PoliceSignSectionType: String, Codable, Hashable
case A = "A"
case B = "B"
case C = "C"
struct PoliceSign: Codable, Hashable, Question //<-- Here
var id: Int?
var image: String?
var sections: [PoliceSignSectionType.RawValue : String]?
var correct: String?
protocol Question : Identifiable //<-- Here
var image: String? get set
struct ContentView : View
@State private var questions : [PoliceSign] = []
@State private var questions2 : [TrafficSign] = []
var body: some View
QuestionCardView(questions: $questions)
QuestionCardView(questions: $questions2)
struct QuestionCardView<T: Question>: View
@Binding var questions: [T]
var body: some View
ForEach(questions) question in
Text(question.image ?? "")
您需要一个定义类型要求的protocol
。在您的原始代码中,看起来 image
是唯一明显的属性。
您的原始代码将具有:
struct QuestionCardView<T: Question>: View
@EnvironmentObject var optionConfigure: OptionConfigure
@Binding var questions: [Question]
【讨论】:
我编辑了我的问题,先生。可以查一下吗? 我已经更新了我的答案。您需要做的就是添加Question
协议,然后确保两个模型都符合它。不需要容器类型。除了将image
设为Optional 属性之外,它与我之前的答案版本基本相同。
非常感谢您的回答,但先生,我没有什么问题。我需要在协议中添加两个不同的枚举。我怎样才能做到这一点 ?因为在打开的下一页中,我需要访问 Enums。
@UfukKöşker 我不确定这到底是什么意思。如果您觉得它与原始问题直接相关,可以编辑问题以添加更多信息来解释它。不过,这实际上听起来可能是一个新问题。如果您发现此答案有帮助,请考虑对其进行投票。
如果您的意思是sections
属性,因为您已将其设置为以enum
s 的原始值作为键的字典,您只需将var sections: [String:String]? get set
添加到协议中即可.以上是关于SwiftUI 通用数组模型的主要内容,如果未能解决你的问题,请参考以下文章
如何将字符串数组从视图模型传递到 swiftUI 中播放歌曲
视图模型数组上的 ForEach 循环问题导致 Xcode 编译错误 - SwiftUI