提问人:Bartłomiej Semańczyk 提问时间:3/23/2023 最后编辑:Bartłomiej Semańczyk 更新时间:3/24/2023 访问量:137
使用元素和选择参数为 SwiftUI 选取器视图创建包装器
Create wrapper for SwiftUI Picker View with elements and selection parameters
问:
这是我的代码:
import SwiftUI
struct VPickerView<T: Hashable>: View {
private let elements: [T]
private let selection: Binding<T>
init(elements: [T], selection: Binding<T>) {
self.elements = elements
self.selection = selection
}
var body: some View {
HStack(spacing: 5) {
ZStack {
Color.green
.frame(width: 45, height: 30)
.cornerRadius(15)
Picker("", selection: $selection) { // Cannot find '$selection' in scope
ForEach(elements, id: \.self) {
Text(String($0))
.font(.title)
.foregroundColor($0 == selection as! T ? .blue : .red)
}
}.onChange(of: selection) { _ in
print("changed")
}
.labelsHidden()
.pickerStyle(.wheel)
.border(.black, width: 5)
.frame(width: 55)
}
}
}
}
但是我收到一个错误,我不知道为什么。Cannot find '$selection' in scope
我想如何使用它?
private let hours: [Int]
@State private var selectedHour: Int = 0
var body: some View {
VPickerView(elements: hours, selection: $selectedHour)
}
条件:
- 所选元素应为蓝色,否则为红色。
- 元素类型可能是 Int、Double、String、Int64
答:
1赞
MarkusMichael Oh
3/23/2023
#1
请记住,SwiftUI 的 Binding 属性允许我们声明一个值实际上来自其他地方,并且应该在共享该属性的人和共享该属性的人之间共享。并且,共享者和共享者 (https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-binding-property-wrapper) 都可以修改绑定属性。
话虽如此,“private let selection: Binding”必须更改为“@Binding var selection: T”,因为 Binding 属性应该同时是 VARIABLE 和 SSHAREABLE(不是私有的)。
此外,由于 Binding 属性 (@Binding) 包装 Binding 实例,因此必须通过执行以下操作来访问其中的内容并对其进行初始化。
init(elements: [T], selection: Binding<T>) {
self.elements = elements
self._selection = selection
}
“_selection”的下栏允许我们到达属性内部并设置绑定属性。
一旦完成这些,编译器仍然不允许你构建提供的代码,因为<T:Hashable>不足以让 Swift 知道 $0(第一个参数)可以转换为 String。
若要解决此问题,可以考虑添加另一个协议一致性,例如 CustomStringConvertible。
struct VPickerView<T: Hashable & CustomStringConvertible>: View {
...codes
}
所以完整的代码可能是这样的:
struct VPickerView<T: Hashable & CustomStringConvertible>: View {
private let elements: [T]
@Binding private var selection: T
init(elements: [T], selection: Binding<T>) {
self.elements = elements
self._selection = selection
}
var body: some View {
HStack(spacing: 5) {
ZStack {
Color.green
.frame(width: 45, height: 30)
.cornerRadius(15)
Picker("", selection: $selection) { // Cannot find '$selection' in scope
ForEach(elements, id: \.self) {
Text($0.description)
.font(.title)
.foregroundColor($0 == selection ? .blue : .red)
}
}.onChange(of: selection) { _ in
print("changed")
}
.labelsHidden()
.pickerStyle(.wheel)
.border(.black, width: 5)
.frame(width: 55)
}
}
}
}
评论
0赞
Bartłomiej Semańczyk
3/24/2023
谢谢你的回答。它有帮助。我还有一个与此相关的问题,但这是另一个问题的主题。
评论
self._selection = selection
$
Binding
@Binding