SwiftUI - 显示符合协议的元素并对元素使用 == 的视图
SwiftUI - View showing Elements conforming to a Protocol and and using == for the Elements
我需要在视图中显示符合通用协议的不同结构的数组。
按照 中的建议,我试过了 - 它工作正常!
现在我需要检查数组元素的相等性。
让协议符合 Equatable
不编译 -
它收到错误:Protocol 'Suggest' can only be used as a generic constraint because it has Self or associated type requirements
.
//protocol Suggest :Equatable {
protocol Suggest {
var desc: String { get }
}
struct Person : Suggest {
var surname : String
var name: String
var id: String { return name }
var desc: String { return name }
}
struct Book : Suggest {
var titel : String
var abstact : String
var id: String { return titel }
var desc: String { return titel }
}
let books = [ Book(titel: "book 1", abstact: "abstract1"),
Book(titel: "book 2", abstact: "abstract2")
]
let persons = [ Person(surname: "John", name: "Doe"),
Person(surname: "Susan", name: "Smith"),
Person(surname: "Frank", name: "Miller")
]
struct ContentView: View {
var body: some View {
VStack {
SuggestList(list: books)
SuggestList(list: persons)
}
}
}
struct SuggestList: View {
var list : [Suggest]
// this line does not compile, if Suggest conforms to Equitable
// "Protocol 'Suggest' can only be used as a generic constraint because it has Self or associated type requirements"
var body: some View {
List(list.indices, id: \.self) { index in
Text(list[index].desc)
// .onTapGesture {
// if list.contains(list[index]){print ("hello")}
// }
}
}
}
你需要使用 <SuggestType: Suggest>
并制作 Suggest 协议 Equatable 然后使用并定义 = = 个人 和书籍
struct ContentView: View {
var body: some View {
VStack {
SuggestList(list: books)
SuggestList(list: persons)
}
}
}
protocol Suggest: Equatable {
var desc: String { get }
}
struct Person: Suggest {
var surname: String
var name: String
var id: String { return name }
var desc: String { return name }
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name
}
}
struct Book: Suggest {
var titel: String
var abstact: String
var id: String { return titel }
var desc: String { return titel }
static func == (lhs: Book, rhs: Book) -> Bool {
return lhs.titel == rhs.titel
}
}
let persons = [Person(surname: "John", name: "Doe"),
Person(surname: "Susan", name: "Smith"),
Person(surname: "Frank", name: "Miller")]
let books = [Book(titel: "book 1", abstact: "abstract1"),
Book(titel: "book 2", abstact: "abstract2")]
struct SuggestList<SuggestType: Suggest>: View {
var list : [SuggestType]
var body: some View {
List(list.indices, id: \.self) { index in
Text(list[index].desc)
.onTapGesture {
if list.contains(list[index]){ print(list[index].desc) }
}
}
}
}
本回答属于评论区问题!关于 Equatable 函数。
如果你没有显式定义 Equatable 函数,那么 Xcode 如果它可以自己推断它会自行处理,有时在复杂的结构中它会要求你显示它当你的结构实例是相等,但是当你显式定义 Equatable 函数时 Xcode 将应用你的自定义规则,例如我创建了 2 种类型的人,在第一个 PersonV1 中我们没有定义 == 但在第二个 PersonV2 中我们确实定义了!因此,Xcode 将在 PersonV2 中接受所有具有相同姓名的人,即使他们有不同的 姓氏 。尝试使用此代码以获得更真实的测试示例。并且 surname 在 PersonV2 中的任何更新都不会占据任何位置,因为它不会计算 PersonV2 的 2 个实例 是否相等!一旦您初始化了 PersonV2 的实例,surname 将不再可更新。您可以尝试更新,但它不会应用,因为无论此实例是否相同,都无所谓!
注意: 我们可以使用此代码使 PersonV2 相等函数对姓氏更改做出反应,但我认为您想像问题中那样使用名称:
static func == (lhs: PersonV2, rhs: PersonV2) -> Bool {
return lhs.name == rhs.name && lhs.surname == rhs.surname
}
struct ContentView: View {
@State private var person1: PersonV1 = PersonV1(surname: "Frank", name: "Miller")
@State private var person2: PersonV2 = PersonV2(surname: "John", name: "Doe")
var body: some View {
VStack(spacing: 50.0) {
VStack(spacing: 20.0) {
Button("update name of person1") { person1.name += " updated!" }
Button("update surname of person1") { person1.surname += " updated!" }
}
.padding()
.background(Color.yellow)
.onChange(of: person1) { newValue in print("onChange for person1:", newValue) }
VStack(spacing: 20.0) {
Button("update name of person2") { person2.name += " updated!" }
Button("update surname of person2") { person2.surname += " updated!" }
}
.padding()
.background(Color.red)
.onChange(of: person2) { newValue in print("onChange for person2:", newValue) }
}
}
}
protocol Suggest: Equatable {
var desc: String { get }
}
struct PersonV1: Suggest {
var surname: String
var name: String
var id: String { return name }
var desc: String { return name }
}
struct PersonV2: Suggest {
var surname: String
var name: String
var id: String { return name }
var desc: String { return name }
static func == (lhs: PersonV2, rhs: PersonV2) -> Bool {
return lhs.name == rhs.name
}
}
我需要在视图中显示符合通用协议的不同结构的数组。
按照
现在我需要检查数组元素的相等性。
让协议符合 Equatable
不编译 -
它收到错误:Protocol 'Suggest' can only be used as a generic constraint because it has Self or associated type requirements
.
//protocol Suggest :Equatable {
protocol Suggest {
var desc: String { get }
}
struct Person : Suggest {
var surname : String
var name: String
var id: String { return name }
var desc: String { return name }
}
struct Book : Suggest {
var titel : String
var abstact : String
var id: String { return titel }
var desc: String { return titel }
}
let books = [ Book(titel: "book 1", abstact: "abstract1"),
Book(titel: "book 2", abstact: "abstract2")
]
let persons = [ Person(surname: "John", name: "Doe"),
Person(surname: "Susan", name: "Smith"),
Person(surname: "Frank", name: "Miller")
]
struct ContentView: View {
var body: some View {
VStack {
SuggestList(list: books)
SuggestList(list: persons)
}
}
}
struct SuggestList: View {
var list : [Suggest]
// this line does not compile, if Suggest conforms to Equitable
// "Protocol 'Suggest' can only be used as a generic constraint because it has Self or associated type requirements"
var body: some View {
List(list.indices, id: \.self) { index in
Text(list[index].desc)
// .onTapGesture {
// if list.contains(list[index]){print ("hello")}
// }
}
}
}
你需要使用 <SuggestType: Suggest>
并制作 Suggest 协议 Equatable 然后使用并定义 = = 个人 和书籍
struct ContentView: View {
var body: some View {
VStack {
SuggestList(list: books)
SuggestList(list: persons)
}
}
}
protocol Suggest: Equatable {
var desc: String { get }
}
struct Person: Suggest {
var surname: String
var name: String
var id: String { return name }
var desc: String { return name }
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name
}
}
struct Book: Suggest {
var titel: String
var abstact: String
var id: String { return titel }
var desc: String { return titel }
static func == (lhs: Book, rhs: Book) -> Bool {
return lhs.titel == rhs.titel
}
}
let persons = [Person(surname: "John", name: "Doe"),
Person(surname: "Susan", name: "Smith"),
Person(surname: "Frank", name: "Miller")]
let books = [Book(titel: "book 1", abstact: "abstract1"),
Book(titel: "book 2", abstact: "abstract2")]
struct SuggestList<SuggestType: Suggest>: View {
var list : [SuggestType]
var body: some View {
List(list.indices, id: \.self) { index in
Text(list[index].desc)
.onTapGesture {
if list.contains(list[index]){ print(list[index].desc) }
}
}
}
}
本回答属于评论区问题!关于 Equatable 函数。
如果你没有显式定义 Equatable 函数,那么 Xcode 如果它可以自己推断它会自行处理,有时在复杂的结构中它会要求你显示它当你的结构实例是相等,但是当你显式定义 Equatable 函数时 Xcode 将应用你的自定义规则,例如我创建了 2 种类型的人,在第一个 PersonV1 中我们没有定义 == 但在第二个 PersonV2 中我们确实定义了!因此,Xcode 将在 PersonV2 中接受所有具有相同姓名的人,即使他们有不同的 姓氏 。尝试使用此代码以获得更真实的测试示例。并且 surname 在 PersonV2 中的任何更新都不会占据任何位置,因为它不会计算 PersonV2 的 2 个实例 是否相等!一旦您初始化了 PersonV2 的实例,surname 将不再可更新。您可以尝试更新,但它不会应用,因为无论此实例是否相同,都无所谓!
注意: 我们可以使用此代码使 PersonV2 相等函数对姓氏更改做出反应,但我认为您想像问题中那样使用名称:
static func == (lhs: PersonV2, rhs: PersonV2) -> Bool {
return lhs.name == rhs.name && lhs.surname == rhs.surname
}
struct ContentView: View {
@State private var person1: PersonV1 = PersonV1(surname: "Frank", name: "Miller")
@State private var person2: PersonV2 = PersonV2(surname: "John", name: "Doe")
var body: some View {
VStack(spacing: 50.0) {
VStack(spacing: 20.0) {
Button("update name of person1") { person1.name += " updated!" }
Button("update surname of person1") { person1.surname += " updated!" }
}
.padding()
.background(Color.yellow)
.onChange(of: person1) { newValue in print("onChange for person1:", newValue) }
VStack(spacing: 20.0) {
Button("update name of person2") { person2.name += " updated!" }
Button("update surname of person2") { person2.surname += " updated!" }
}
.padding()
.background(Color.red)
.onChange(of: person2) { newValue in print("onChange for person2:", newValue) }
}
}
}
protocol Suggest: Equatable {
var desc: String { get }
}
struct PersonV1: Suggest {
var surname: String
var name: String
var id: String { return name }
var desc: String { return name }
}
struct PersonV2: Suggest {
var surname: String
var name: String
var id: String { return name }
var desc: String { return name }
static func == (lhs: PersonV2, rhs: PersonV2) -> Bool {
return lhs.name == rhs.name
}
}