样式为DefaultPickerStyle()的SwiftUI选择器不工作
使用Swift5.2.3、iOS14.4.2、XCode12.4、 在SwiftUI中使用样式为DefaultPickerStyle()的SwiftUI选择器不工作,swiftui,environmentobject,defaultpickerstyle,menupickerstyle,Swiftui,Environmentobject,Defaultpickerstyle,Menupickerstyle,使用Swift5.2.3、iOS14.4.2、XCode12.4、 在SwiftUI中使用.sheet修饰符一开始让我感到兴奋,因为它似乎是一种显示模式表的简单而有效的方法 然而,在现实世界的应用程序中,.sheet几乎可以集成 以下是发现的两个bug(除其他外…): 错误1:当在图纸的分段选择器中时,具有DefaultPickerStyle的选择器不工作 错误2:工作表不会偶尔关闭() 现在让我们关注Bug Nr1:“当在图纸的分段选择器中时,具有DefaultPickerStyle的选择器不
.sheet
修饰符一开始让我感到兴奋,因为它似乎是一种显示模式表的简单而有效的方法
然而,在现实世界的应用程序中,.sheet
几乎可以集成
以下是发现的两个bug(除其他外…):
错误1:当在图纸的分段选择器中时,具有DefaultPickerStyle的选择器不工作
错误2:工作表不会偶尔关闭()
现在让我们关注Bug Nr1:“当在图纸的分段选择器中时,具有DefaultPickerStyle的选择器不工作”
我的意思可以在这个例子中看到。这是一个真实世界应用程序的摘录。(是的,我需要放置如此多的视图,因为普通教科书的示例工作得非常好——但一旦变得稍微复杂一点就不行了…)
请注意,“可怕的儿童”实际上是.pickerStyle(DefaultPickerStyle())
!(您可以在名为SettingsView
的最底部视图中找到它
如果我用.pickerStyle(MenuPickerStyle())
替换该样式,那么应用程序运行得非常好
DefaultPickerStyle()
有什么问题
请参见以下两个说明问题的视频:
Video-1:FAULT显示DefaultPickerStyle()
(您可以看到,.onChange(of:categoryIndex){(idx)in…}
从未使用此选择器样式调用过…)
视频-2:正确显示MenuPickerStyle()
ContentView如下所示:
enum THSheetSelection: Hashable, Identifiable {
case infoSettings
var id: THSheetSelection { self }
}
struct ContentView: View {
@State var sheetState: THSheetSelection?
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Button("Show Settings Sheet") {
sheetState = .infoSettings
}
}
.sheet(item: $sheetState) { state in
switch state {
case .infoSettings:
InfoSettingsView()
}
}
}
}
struct InfoSettingsView: View {
@Environment(\.presentationMode) var presentationMode
@State private var segmentSelection = 0
@State private var infoShown = false
var body: some View {
NavigationView {
VStack {
Picker("", selection: $segmentSelection) {
Text("Info").tag(0)
Text("Settiongs").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.background(Color.blue)
.padding()
switch segmentSelection {
case 0:
InfoView()
case 1:
SettingsView()
default:
InfoView()
}
}
.navigationBarTitle("Info & Settings")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Text("Done")
}
}
}
.onAppear {
segmentSelection = 0
}
}
}
}
struct InfoView: View {
@Environment(\.presentationMode) var presentationMode
let versionNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String) ?? ""
let buildNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String) ?? ""
var body: some View {
VStack {
Form {
Section(header: Text("App Info")) {
HStack {
Text("App Version")
Spacer()
Text("v\(versionNr) (\(buildNr))")
}
}
}
.ignoresSafeArea()
Spacer()
}
}
}
struct SettingsView: View {
@State private var categoryIndex = 0
var categorySelection = ["Choice 1", "Choice 2", "Choice 3", "Choice 4"]
var body: some View {
VStack {
Form {
Section(header: Text(LocalizedStringKey("InterDeviceCommKey"))) {
Picker(selection: $categoryIndex, label: Text(LocalizedStringKey("TechChoiceKey"))) {
ForEach(0 ..< categorySelection.count, id: \.self) { idx in
Text(categorySelection[idx]).tag(idx)
}
}
.pickerStyle(DefaultPickerStyle()) // does NOT behave correctly
// .pickerStyle(MenuPickerStyle()) // does behave correctly
.onChange(of: categoryIndex) { (idx) in /// ????????? why this never gets called with DefaultPickerStyle() ?????????
print("categoryChanged to index \(idx)")
}
}
Section(header: Text("Selected Choice")) {
HStack {
Text("My choice")
Spacer()
Text("\(categorySelection[categoryIndex])")
}
}
.ignoresSafeArea()
}
Spacer()
}
}
}
信息设置视图如下所示:
enum THSheetSelection: Hashable, Identifiable {
case infoSettings
var id: THSheetSelection { self }
}
struct ContentView: View {
@State var sheetState: THSheetSelection?
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Button("Show Settings Sheet") {
sheetState = .infoSettings
}
}
.sheet(item: $sheetState) { state in
switch state {
case .infoSettings:
InfoSettingsView()
}
}
}
}
struct InfoSettingsView: View {
@Environment(\.presentationMode) var presentationMode
@State private var segmentSelection = 0
@State private var infoShown = false
var body: some View {
NavigationView {
VStack {
Picker("", selection: $segmentSelection) {
Text("Info").tag(0)
Text("Settiongs").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.background(Color.blue)
.padding()
switch segmentSelection {
case 0:
InfoView()
case 1:
SettingsView()
default:
InfoView()
}
}
.navigationBarTitle("Info & Settings")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Text("Done")
}
}
}
.onAppear {
segmentSelection = 0
}
}
}
}
struct InfoView: View {
@Environment(\.presentationMode) var presentationMode
let versionNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String) ?? ""
let buildNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String) ?? ""
var body: some View {
VStack {
Form {
Section(header: Text("App Info")) {
HStack {
Text("App Version")
Spacer()
Text("v\(versionNr) (\(buildNr))")
}
}
}
.ignoresSafeArea()
Spacer()
}
}
}
struct SettingsView: View {
@State private var categoryIndex = 0
var categorySelection = ["Choice 1", "Choice 2", "Choice 3", "Choice 4"]
var body: some View {
VStack {
Form {
Section(header: Text(LocalizedStringKey("InterDeviceCommKey"))) {
Picker(selection: $categoryIndex, label: Text(LocalizedStringKey("TechChoiceKey"))) {
ForEach(0 ..< categorySelection.count, id: \.self) { idx in
Text(categorySelection[idx]).tag(idx)
}
}
.pickerStyle(DefaultPickerStyle()) // does NOT behave correctly
// .pickerStyle(MenuPickerStyle()) // does behave correctly
.onChange(of: categoryIndex) { (idx) in /// ????????? why this never gets called with DefaultPickerStyle() ?????????
print("categoryChanged to index \(idx)")
}
}
Section(header: Text("Selected Choice")) {
HStack {
Text("My choice")
Spacer()
Text("\(categorySelection[categoryIndex])")
}
}
.ignoresSafeArea()
}
Spacer()
}
}
}
InfoView如下所示:
enum THSheetSelection: Hashable, Identifiable {
case infoSettings
var id: THSheetSelection { self }
}
struct ContentView: View {
@State var sheetState: THSheetSelection?
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Button("Show Settings Sheet") {
sheetState = .infoSettings
}
}
.sheet(item: $sheetState) { state in
switch state {
case .infoSettings:
InfoSettingsView()
}
}
}
}
struct InfoSettingsView: View {
@Environment(\.presentationMode) var presentationMode
@State private var segmentSelection = 0
@State private var infoShown = false
var body: some View {
NavigationView {
VStack {
Picker("", selection: $segmentSelection) {
Text("Info").tag(0)
Text("Settiongs").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.background(Color.blue)
.padding()
switch segmentSelection {
case 0:
InfoView()
case 1:
SettingsView()
default:
InfoView()
}
}
.navigationBarTitle("Info & Settings")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Text("Done")
}
}
}
.onAppear {
segmentSelection = 0
}
}
}
}
struct InfoView: View {
@Environment(\.presentationMode) var presentationMode
let versionNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String) ?? ""
let buildNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String) ?? ""
var body: some View {
VStack {
Form {
Section(header: Text("App Info")) {
HStack {
Text("App Version")
Spacer()
Text("v\(versionNr) (\(buildNr))")
}
}
}
.ignoresSafeArea()
Spacer()
}
}
}
struct SettingsView: View {
@State private var categoryIndex = 0
var categorySelection = ["Choice 1", "Choice 2", "Choice 3", "Choice 4"]
var body: some View {
VStack {
Form {
Section(header: Text(LocalizedStringKey("InterDeviceCommKey"))) {
Picker(selection: $categoryIndex, label: Text(LocalizedStringKey("TechChoiceKey"))) {
ForEach(0 ..< categorySelection.count, id: \.self) { idx in
Text(categorySelection[idx]).tag(idx)
}
}
.pickerStyle(DefaultPickerStyle()) // does NOT behave correctly
// .pickerStyle(MenuPickerStyle()) // does behave correctly
.onChange(of: categoryIndex) { (idx) in /// ????????? why this never gets called with DefaultPickerStyle() ?????????
print("categoryChanged to index \(idx)")
}
}
Section(header: Text("Selected Choice")) {
HStack {
Text("My choice")
Spacer()
Text("\(categorySelection[categoryIndex])")
}
}
.ignoresSafeArea()
}
Spacer()
}
}
}
设置视图如下所示:
enum THSheetSelection: Hashable, Identifiable {
case infoSettings
var id: THSheetSelection { self }
}
struct ContentView: View {
@State var sheetState: THSheetSelection?
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Button("Show Settings Sheet") {
sheetState = .infoSettings
}
}
.sheet(item: $sheetState) { state in
switch state {
case .infoSettings:
InfoSettingsView()
}
}
}
}
struct InfoSettingsView: View {
@Environment(\.presentationMode) var presentationMode
@State private var segmentSelection = 0
@State private var infoShown = false
var body: some View {
NavigationView {
VStack {
Picker("", selection: $segmentSelection) {
Text("Info").tag(0)
Text("Settiongs").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.background(Color.blue)
.padding()
switch segmentSelection {
case 0:
InfoView()
case 1:
SettingsView()
default:
InfoView()
}
}
.navigationBarTitle("Info & Settings")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Text("Done")
}
}
}
.onAppear {
segmentSelection = 0
}
}
}
}
struct InfoView: View {
@Environment(\.presentationMode) var presentationMode
let versionNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String) ?? ""
let buildNr: String = (Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String) ?? ""
var body: some View {
VStack {
Form {
Section(header: Text("App Info")) {
HStack {
Text("App Version")
Spacer()
Text("v\(versionNr) (\(buildNr))")
}
}
}
.ignoresSafeArea()
Spacer()
}
}
}
struct SettingsView: View {
@State private var categoryIndex = 0
var categorySelection = ["Choice 1", "Choice 2", "Choice 3", "Choice 4"]
var body: some View {
VStack {
Form {
Section(header: Text(LocalizedStringKey("InterDeviceCommKey"))) {
Picker(selection: $categoryIndex, label: Text(LocalizedStringKey("TechChoiceKey"))) {
ForEach(0 ..< categorySelection.count, id: \.self) { idx in
Text(categorySelection[idx]).tag(idx)
}
}
.pickerStyle(DefaultPickerStyle()) // does NOT behave correctly
// .pickerStyle(MenuPickerStyle()) // does behave correctly
.onChange(of: categoryIndex) { (idx) in /// ????????? why this never gets called with DefaultPickerStyle() ?????????
print("categoryChanged to index \(idx)")
}
}
Section(header: Text("Selected Choice")) {
HStack {
Text("My choice")
Spacer()
Text("\(categorySelection[categoryIndex])")
}
}
.ignoresSafeArea()
}
Spacer()
}
}
}
结构设置视图:视图{
@国家私有变量类别索引=0
变量类别选择=[“选择1”、“选择2”、“选择3”、“选择4”]
var body:一些观点{
VStack{
形式{
节(标题:文本(LocalizedStringKey(“InterDeviceCommKey”)){
选择器(选择:$categoryIndex,标签:文本(LocalizedStringKey(“TechChoiceKey”)){
ForEach(0...sheet
的DefaultPickerStyle()在上述情况下不能正常工作吗