Xcode:版本11.3(11C29)
目标:运行iOS 13.3的模拟器
使用表格和SwiftUI时出现不一致的行为,很难诊断。当我:
*使用NavigationView
本身中的按钮,我可以始终调出工作表并将其关闭
*使用NavigationView
(即navigationBarItems
)栏中的按钮,行为不一致:有时会切换而不会出现问题,有时会“锁定”并且在运行前约10秒钟没有响应再次。在界面中四处滑动并执行其他操作似乎有助于“重置”功能。
最小的可复制示例:
import SwiftUI
struct ContentView: View {
@State var isModalShowing = false
var body: some View {
NavigationView {
VStack {
List {
ForEach(1..<5) { number in
Text(String(number))
}
}
Button("First Modal Button") {
self.isModalShowing = true
}
}
.navigationBarItems(leading:
Button("Second Modal Button") {
self.isModalShowing = true
})
}
.sheet(isPresented: $isModalShowing) {
TestView(isPresented: self.$isModalShowing)
}
}
}
struct TestView: View {
@Binding var isPresented: Bool
var body: some View {
VStack {
Text("Hello SwiftUI!")
Button("Dismiss") {
self.isPresented = false
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
注意:
*连续按First modal button
即可
*首次关闭模态后,按Second modal button
会产生不一致的效果(尝试连续约5-10次使用此按钮,它应该会锁定,但是很难预测何时会出现)
已经有a few个StackOverflow问题/ answers about this,但是到目前为止,没有一个问题对我有用,他们似乎在谈论Xcode Beta,而我现在还很稳定(希望11.3是稳定的)。传递状态的不同方式(@Binding
和@Environment
)无济于事。在.sheet
被调用的地方移动也没有任何改变。我认为它也与List
和/或ForEach
有关,但是我是Swift的新手,不确定如何进一步调试。
答案 0 :(得分:1)
我相信这是一个错误。尽管我的答案不会解决这个问题,但是可以给您选择的机会。
出于好奇,我对视图层次结构进行了一些调试。在当前设置下,导航栏按钮最初位于此处(突出显示为蓝色):
然后,您需要提交纸页并相应地解散纸页。解雇后,导航栏按钮的位置不太正确。参见:
按钮的Text
保持在正确的位置,但是条形按钮从应有的位置移开了。
但是,如果您使用NavigationLink
而非.sheet
演示文稿,则不会发生这种移位。
好吧,此问题在导航栏标题的large
的{{1}}选项中很普遍,并且很长一段时间以来都是默认设置。但是,如果使用TitleDisplayMode
选项,则该问题不存在。使用inline
选项,在解雇工作表前后,请注意导航栏按钮将停留在同一位置:
因此,您现在可以考虑两个选项:
使用inline
代替工作表演示。您可以通过将以下代码放在最外面的NavigationLink
(在您的情况下为View
)中来实现此目的:
VStack
注意:此
的更多信息NavigationLink(destination: TestView(), isActive: self.$isModalShowing) { EmptyView() // no need to provide any other view as it will be triggered by the action // of navigation bar button item which already provides its own view }
选项未在 Xcode 11.3 或更高版本上进行过测试,因为此版本的导航链接似乎不正常。但可以正常使用,直到 Xcode 11.2.1 。有关SwiftUI unable to navigate back and forth with navigationLink
将导航栏NavigationLink
的{{1}}选项用作:
inline
答案 1 :(得分:0)
解散模态表的另一种方法:
struct TestView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("Hello SwiftUI!")
Button("Dismiss") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
答案 2 :(得分:0)
这里没有一个解决方案对我有用,但是这个解决方案确实可以-下拉到UIKit来使用另一个dismiss
函数:What is different between @Binding and scroll down to dismiss presented view?
答案 3 :(得分:0)
通过将文本视图与onTapGesture结合使用,有一种解决方法,但是,点击该按钮时,您将失去按钮颜色的动画。
代码类似于:
.navigationBarItems(leading:
Text("Text")
.onTapGesture {
self.isPresentingSheet = true
}
.sheet(isPresented: self.$isPresentingSheet, content: {
SheetView()
})
)
答案 4 :(得分:0)
我找到了一种替代方法来解决此问题,同时仍使用按钮和大标题。这是代码:
struct ContentView: View {
@State var isModalShowing = false
@State var opacity: Double = 1
var body: some View {
NavigationView() {
List() {
// Some views here
}
.navigationBarTitle(Text("Home"), displayMode: .automatic)
.navigationBarItems(trailing:
Button(action: {
self.opacity = 0.5
self.isModalShowing = true
}, label: {
Image(systemName: "plus")
})
.opacity(self.opacity)
.scaleEffect(1.5)
.sheet(isPresented: $isModalShowing,
onDismiss: {
self.opacity = 1
},
content: {
NewView(onDismiss: self.$isModalShowing)
})
)
}
}
}
基本上,我们在点击按钮时更改不透明度,而在关闭工作表时将其更改为不透明度,我认为这将迫使按钮自行更新。
关于解散纸张,在这种情况下,OP的工作方式有效