Amy*_*ose 2 view picker swift swiftui
我知道这是一个奇怪的标题,但有很多帖子具有相似的标题和完全不同的问题。大多数人View在他们的视图中编写除代码之外的其他内容,而我没有这样做(据我所知)。
我正在尝试Picker与其他BinaryInteger类型兼容,因为它不适用于除 之外的任何类型Int,并且我在使预览正常工作时遇到了一些麻烦。这是代码:
import SwiftUI
struct CompatibilityPicker<Label, SelectionValue, Content> : View where Label : StringProtocol, SelectionValue : BinaryInteger, Content : View {
var content : () -> Content
var label : Label
@Binding private var _selection : SelectionValue
private var selection: Binding<Int> { Binding<Int>(
get: {
Int(_selection)
},
set: {
self._selection = SelectionValue($0)
})
}
init(_ label : Label, selection : SelectionValue, content : @escaping () -> Content) {
self.label = label
self._selection = selection
self.content = content
}
var body: some View {
Picker(label, selection: selection, content: content)
}
}
struct CompatibilityPicker_Previews: PreviewProvider {
@State static var selection : UInt8 = 4
static var previews: some View {
CompatibilityPicker("Difficulty", selection: selection) { //error : Type'()' cannot conform to 'View'
Text("Easy").tag(0)
Text("Normal").tag(1)
Text("Hard").tag(2)
}
}
}
Run Code Online (Sandbox Code Playgroud)
是什么赋予了 ?我有一个正常的Picker,使用完全相同的语法并且有效,我不知道我做错了什么。
感谢 @RobMayoff 的解决方案,我又向前迈进了一步,但是出现了看似荒谬的错误,但无法用 cmd+shift+k 清除:
init(_ label : Label, selection : SelectionValue, @ViewBuilder content : @escaping () -> Content) {
self.content = content
self.label = label
self._selection = selection //variable self._selection used before initialised
// This stays on this line if I change the order,
} // Return from initializer without initialising all stored properties
// That is not true, as far as I can tell
Run Code Online (Sandbox Code Playgroud)
巧妙的是,您试图ViewBuilder在尾随闭包中使用语法,但您没有装饰content注释@ViewBuilder。所以 Swift 推断尾随闭包返回()(也称为Void)。
更改init声明以提及@ViewBuilder:
struct CompatibilityPicker<blah blah blah>: View where blah blah blah {\n\n init(\n _ label : Label,\n selection : SelectionValue,\n @ViewBuilder content : @escaping () -> Content\n // ^^^^^^^^^^^^\n ) {\n blah blah blah\nRun Code Online (Sandbox Code Playgroud)\n @Binding private var _selection : SelectionValue\n\n blah blah blah\n\n init(_ label : Label, selection : SelectionValue, content : @escaping () -> Content) {\n self.label = label\n self._selection = selection\n self.content = content\n }\nRun Code Online (Sandbox Code Playgroud)\n该_selection变量由包装器包装Binding,这意味着它实际上是一个计算属性。存储的属性被命名__selection(注意两个下划线)并且类型为Binding<SelectionValue>。因为_selection是计算属性,init所以在所有存储的属性都初始化之前不能提及它。也许你应该改变init以采取Binding<SelectionValue>争论而不是SelectionValue参数:
init(\n _ label : Label,\n selection : Binding<SelectionValue>,\n @ViewBuilder content : @escaping () -> Content\n // ^^^^^^^^^^^^\n ) {\n self.label = label\n self.content = content\n __selection = selection\n }\nRun Code Online (Sandbox Code Playgroud)\n我查看了您的其他问题和您的代码,我想我知道您的意思 \xe2\x80\x9cit 不适用于除Int\xe2\x80\x9d 之外的任何东西。
问题是,当你说 时Text("Easy").tag(0),Swift 将0其视为Int. 如果您的Picker\SelectionValue是,比如说,Int16那么确实Picker将无法使用0标记,因为类型不匹配。
您可以通过提供正确的类型tag来完成您的工作。例如:。Picker0Text("Easy").tag(0 as Int16)
然而,我的建议是你不要再胡思乱想了CompatibilityPicker。这是原始痴迷的症状。惯用的解决方案是使用 anenum作为标签:
enum Difficulty: Hashable {\n case easy\n case medium\n case hard\n}\n\nstruct Demo1: View {\n @State var difficulty: Difficulty = .easy\n\n var body: some View {\n Picker("Difficulty", selection: $difficulty) {\n Text("Easy").tag(Difficulty.easy)\n Text("Medium").tag(Difficulty.medium)\n Text("Hard").tag(Difficulty.hard)\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n你可以更进一步,这样做:
\nextension Difficulty: CaseIterable { }\n\nextension Difficulty {\n var stringKey: LocalizedStringKey {\n switch self {\n case .easy: return "Easy"\n case .medium: return "Medium"\n case .hard: return "Hard"\n }\n }\n}\n\nstruct Demo2: View {\n @State var difficulty: Difficulty = .easy\n\n var body: some View {\n Picker("Difficulty", selection: $difficulty) {\n ForEach(Difficulty.allCases, id: \\.self) {\n Text($0.stringKey).tag($0)\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2144 次 |
| 最近记录: |