【发布时间】:2022-03-20 11:07:53
【问题描述】:
使用Swift5.2.3、iOS14.4.2、XCode12.4,
在 SwiftUI 中使用 .sheet 修饰符让我一开始感到很兴奋,因为它似乎是一种显示模式表的简单有效的方式。
但是,在实际应用程序中,.sheet 几乎可以集成。
这里发现了两个错误:
错误 1:工作表不会偶尔关闭
错误 2:带 DefaultPickerStyle 的选取器在工作表的 SegmentPicker (See this Stackoverlow-question that I created) 内时不起作用
现在让我们关注 Bug Nr1:“工作表未关闭”:
cmd presentationMode.wrappedValue.dismiss() 应该关闭工作表。它适用于 90% 的情况。但每隔一段时间,在不解释其原因的情况下,模态表并没有关闭。
这是一段代码摘录:
import SwiftUI
import Firebase
struct MyView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Form {
Section(header: Text("Login")) {
Button(action: {
UserDefaults.standard.set(true, forKey: AppConstants.UserDefaultKeys.justLogoutLoginPressed)
try? Auth.auth().signOut()
// supposedly should work all the time - but it only works 90% of the time.....
presentationMode.wrappedValue.dismiss()
}) {
HStack {
Text((Auth.auth().currentUser?.isAnonymous ?? true) ? "Login" : "Logout")
Spacer()
}
}
}
}
.ignoresSafeArea()
Spacer()
}
}
}
我还尝试将关闭调用包装在主线程中:
DispatchQueue.main.async {
presentationMode.wrappedValue.dismiss()
}
但这并没有帮助。
知道为什么 SwiftUI .sheets 不会使用 presentationMode 关闭它吗??
在这里,我首先添加了调用工作表的方式。由于从一个更大的应用程序中取出,我显然在这里只展示了如何调用工作表的示例:
import SwiftUI
@main
struct TestKOS005App: App {
@StateObject var appStateService = AppStateService(appState: .startup)
var body: some Scene {
WindowGroup {
MainView()
.environmentObject(appStateService)
}
}
}
class AppStateService: ObservableObject {
@Published var appState: THAppState
var cancellableSet = Set<AnyCancellable>()
init(appState: THAppState) {
self.appState = appState
}
// ...
}
enum THAppState: Equatable {
case startup
case downloading
case caching
case waiting
case content(tagID: String, name: String)
case cleanup
}
struct MainView: View {
@EnvironmentObject var appStateService: AppStateService
@State var sheetState: THSheetSelection?
init() {
UINavigationBar.appearance().tintColor = UIColor(named: "title")
}
var body: some View {
ZStack {
NavigationView {
ZStack {
switch appStateService.appState {
case .caching:
Text("caching")
case .waiting:
Text("waiting")
case .content(_, _):
VStack {
Text("content")
Button(action: {
sheetState = .sheetType3
}, label: {
Text("Button")
})
}
default:
Text("no screen")
}
}
.sheet(item: $sheetState) { state in
switch state {
case .sheetType1:
Text("sheetType1")
case .sheetType2:
Text("sheetType2")
case .sheetType3:
MyView()
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
}
enum THSheetSelection: Hashable, Identifiable {
case sheetType1
case sheetType2
case sheetType3
var id: THSheetSelection { self }
}
【问题讨论】:
-
我在您的代码中没有看到工作表。请提供最小的可重现示例。
-
请提供您从中调用
MyView的视图代码。 -
我提供了您要求的代码。由于这是一个相当复杂的应用程序,我提供了整个应用程序的最小摘录。但这给了你这个想法。如您所见,通过按下按钮在 MainView 中的
NavigationView内调用工作表。
标签: swiftui dismiss environmentobject modal-view