问题是我添加了一个工具栏“完成”按钮,但是当我在同一视图上显示警报然后重新聚焦于文本字段时,工具栏“完成”按钮会在 SwiftUI 中自动消失。在
TitleWithTextfield
中,有一个文本字段和一个标签。我已经实施了验证;例如,如果文本字段为空并且用户点击提交按钮,则会显示一条警报,提示用户输入姓名或电子邮件。但是,当用户按下“确定”按钮并再次点击文本字段后,工具栏的“完成”按钮会自动消失。
这是代码:
var body: some View {
NavigationView {
ZStack {
AppColors.primaryColor
.ignoresSafeArea(.all)
VStack {
NavigationViewWithTitleInCenter(title: "Feedback", backButtonAction: {
// Call your function here
presentationMode.wrappedValue.dismiss()
print("Back button tapped!")
})
Spacer()
VStack {
TitleWithTextfield(placeholder: "Enter Name", text: $name)
TitleWithTextfield(placeholder: "Enter Email", text: $email)
TitleWithTextfield(placeholder: "Enter Subject", text: $subject)
TitleWithTextView(placeholder: "Enter Message", text: $description)
PrimaryButton(title: "Submit").onTapGesture {
self.didTapSubmit()
}
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
.foregroundColor(.blue)
}
}
Spacer()
}
.blur(radius: isLoading ? 1 : 0) // Apply blur when isLoading is true
.loadingOverlay(isLoading: isLoading)
}
.alert(isPresented: $showAlert) {
Alert(title: Text("Message"), message: Text("\(alertMessage)"), dismissButton: .default(Text("OK")))
}
}
}
我找到了一种更适合 SwiftUI 的方法来解决 SwiftUI 和 iOS 中工具栏(导航栏)消失的问题。 我使用工具栏来执行非常重要的命令 - 替代 macOS 中的应用程序菜单。因此,缺少工具栏会导致我的 iOS 应用程序瘫痪。它永远不应该(!)发生。然而,多种情况使其消失(例如当我关闭弹出视图或在主视图中滚动时)。为此,我似乎找到了一个切实可行的解决办法。 首先是生成工具栏的模板代码 - 这是用于在我的应用程序中生成基本内容视图的符号代码。
struct ContentView: View {
var body: some View {
// The NavigationStack ensures the presence of the navigationBar (toolBar)
let theView =
NavigationStack(root: {self.generateContentView()})
return theView
}
func generateContentView() -> some View {
let theView =
Text("This is my content view")
.toolbar {self.generateToolBar()}
}
@ToolbarContentBuilder
func generateToolBar() -> some ToolbarContent {
ToolbarItem(placement: .navigationBarTrailing) {
Text("This is a toolbar item")
}
}
}
我的解决方案是,如果我无法阻止系统做出不显示工具栏的决定,我可以尝试通过将状态变量 navigationBarIsHidden 设置为 false 来撤消隐藏。
这里更新的代码在收到通知“renewToolbar”时将状态变量 naviationBarIsHidden 设置为 false。请注意 ContentView 的修饰符
.navigationBarHidden(self.navigationBarIsHidden)
以及通过 Task()
将 navigationBarIsHidden 延迟更改为 false。
struct ContentView: View {
let document:ApplicationDocument
@State var navigationBarIsHidden : Bool = false
var body: some View {
// The NavigationStack ensures the presence of the navigationBar (toolBar)
let theView =
NavigationStack(root: {self.generateContentView()})
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name(rawValue: "renewToolbar"), object: self.document), perform: { notification in
self.navigationBarIsHidden = true
Task() {
self.navigationBarIsHidden = false
}})
return theView
}
func generateContentView() -> some View {
let theView =
Text("This is my content view")
.toolbar {self.generateToolBar()}
.navigationBarHidden(self.navigationBarIsHidden)
}
@ToolbarContentBuilder
func generateToolBar() -> some ToolbarContent {
ToolbarItem(placement: .navigationBarTrailing) {
Text("This is a toolbar item")
}
}
}
问题仍然存在:如果各种各样的事件都会导致导航栏消失,我应该什么时候发送此通知?解决方案是将其绑定到工具栏项本身之一的 .onDisappear 修饰符。
这是完整的代码:
struct ContentView: View {
let document:ApplicationDocument
@State var navigationBarIsHidden : Bool = false
var body: some View {
// The NavigationStack ensures the presence of the navigationBar (toolBar)
let theView =
NavigationStack(root: {self.generateContentView()})
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name(rawValue: "renewToolbar"), object: self.document), perform: { notification in
self.navigationBarIsHidden.toggle()
Task() {
self.navigationBarIsHidden.toggle()
}})
return theView
}
func generateContentView() -> some View {
let theView =
Text("This is my content view")
.toolbar {self.generateToolBar()}
.navigationBarHidden(self.navigationBarIsHidden)
}
@ToolbarContentBuilder
func generateToolBar() -> some ToolbarContent {
ToolbarItem(placement: .navigationBarTrailing) {
Text("This is a toolbar item")
.onDisappear(perform: {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "renewToolbar"), object: self.document)
})
}
}
}
在我的实际应用程序中,我的通知实际上绑定到 TextField(搜索字段)而不是文本,以防万一这不是针对文本调用的。
结果是,当我关闭弹出视图时,工具栏仍然消失,但此后它立即重新出现。
我尝试了按照上面的建议更新视图 id 的解决方案。它对我不起作用。在 SwiftUI 中,替换 id 是一项繁重的操作,因为如果强制重新渲染整个视图层次结构。整个视图(在我的例子中:整个屏幕)都会重建。