Rob*_*ert 34 uinavigationcontroller ios swift swiftui xcode11.2
最小的可重现示例(Xcode 11.2 beta,在Xcode 11.1中有效):
struct Parent: View {
var body: some View {
NavigationView {
Text("Hello World")
.navigationBarItems(
trailing: NavigationLink(destination: Child(), label: { Text("Next") })
)
}
}
}
struct Child: View {
@Environment(\.presentationMode) var presentation
var body: some View {
Text("Hello, World!")
.navigationBarItems(
leading: Button(
action: {
self.presentation.wrappedValue.dismiss()
},
label: { Text("Back") }
)
)
}
}
struct ContentView: View {
var body: some View {
Parent()
}
}
Run Code Online (Sandbox Code Playgroud)
问题似乎在于将我放置NavigationLink在navigationBarItems嵌套于SwiftUI视图(其根视图为)的修改器内部NavigationView。崩溃报告表明,当我向前导航Child然后返回时,我试图弹出一个不存在的视图控制器Parent。
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to pop to a view controller that doesn't exist.'
*** First throw call stack:
Run Code Online (Sandbox Code Playgroud)
如果我将其放置NavigationLink在如下所示的视图主体中,则效果很好。
struct Parent: View {
var body: some View {
NavigationView {
NavigationLink(destination: Child(), label: { Text("Next") })
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是SwiftUI错误还是预期行为?
编辑:我已经在Apple的反馈助手中给ID开了一个问题,FB7423964以防Apple有人担心:)。
编辑:我在反馈助手中打开票证表明有10多个类似的已报告问题。他们已使用更新了分辨率Resolution: Potential fix identified - For a future OS update。手指交叉,修复很快就到了。
Jus*_*gan 14
这对我来说是很痛苦的一点!我把它留了下来,直到我的大多数应用程序完成为止,并且我有足够的空间来处理崩溃问题。
我想我们都可以同意SwifUI有一些很棒的东西,但是调试可能很困难。
我认为这是一个错误。这是我的基本原理:
如果以大约半秒的异步延迟包装presentationMode dismiss调用,则应该发现该程序将不再崩溃。
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.presentationMode.wrappedValue.dismiss()
}
Run Code Online (Sandbox Code Playgroud)这向我表明,该错误是SwiftUI如何与所有其他UIKit代码进行界面交互以管理各种视图的深处的意外行为。根据您的实际代码,您可能会发现,如果视图中存在一些较小的复杂性,则崩溃实际上不会发生。例如,如果您从一个视图中退出到一个具有列表的视图,并且该列表为空,则将在没有异步延迟的情况下崩溃。另一方面,如果在该列表视图中甚至只有一个条目,则强制循环迭代以生成父视图,您将看到崩溃不会发生。
我不太确定我将延迟中的dismiss调用包装起来的解决方案有多么健壮。我必须测试更多。如果您对此有任何想法,请告诉我!我很高兴向您学习!
这是一个主要的错误,我找不到解决它的正确方法。在iOS 13 / 13.1上工作正常,但13.2崩溃。
您实际上可以用一种更简单的方式来复制它(此代码实际上就是您所需要的)。
struct ContentView: View {
var body: some View {
NavigationView {
Text("Hello, World!").navigationBarTitle("To Do App")
.navigationBarItems(leading: NavigationLink(destination: Text("Hi")) {
Text("Nav")
}
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
希望苹果能解决这个问题,因为它肯定会破坏SwiftUI应用程序(包括我的)的负载。
This also has frustrated me for quite some time. Over the past few months, depending on the Xcode version, simulator version and real device type and/or version, it has gone from working to failing to working again, seemingly at random. However, recently it has been failing consistently for me, so yesterday I took a deep dive into it. I am currently using Xcode Version 11.2.1 (11B500).
看来问题围绕着导航栏和按钮的添加方式。因此,我没有使用按钮本身的NavigationLink(),而是尝试使用具有设置@State var的动作的标准Button()来激活隐藏的NavigationLink。这是罗伯特父视图的替代品:
struct Parent: View {
@State private var showingChildView = false
var body: some View {
NavigationView {
VStack {
Text("Hello World")
NavigationLink(destination: Child(),
isActive: self.$showingChildView)
{ EmptyView() }
.frame(width: 0, height: 0)
.disabled(true)
.hidden()
}
.navigationBarItems(
trailing: Button(action:{ self.showingChildView = true }) { Text("Next") }
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这在所有模拟器和所有真实设备上都非常一致地工作。
这是我的助手视图:
struct HiddenNavigationLink<Destination : View>: View {
public var destination: Destination
public var isActive: Binding<Bool>
var body: some View {
NavigationLink(destination: self.destination, isActive: self.isActive)
{ EmptyView() }
.frame(width: 0, height: 0)
.disabled(true)
.hidden()
}
}
struct ActivateButton<Label> : View where Label : View {
public var activates: Binding<Bool>
public var label: Label
public init(activates: Binding<Bool>, @ViewBuilder label: () -> Label) {
self.activates = activates
self.label = label()
}
var body: some View {
Button(action: { self.activates.wrappedValue = true }, label: { self.label } )
}
}
Run Code Online (Sandbox Code Playgroud)
这是用法示例:
struct ContentView: View {
@State private var showingAddView: Bool = false
var body: some View {
NavigationView {
VStack {
Text("Hello, World!")
HiddenNavigationLink(destination: AddView(), isActive: self.$showingAddView)
}
.navigationBarItems(trailing:
HStack {
ActivateButton(activates: self.$showingAddView) { Image(uiImage: UIImage(systemName: "plus")!) }
EditButton()
} )
}
}
}
Run Code Online (Sandbox Code Playgroud)
作为一种解决方法,根据上面 Chuck H 的回答,我将 NavigationLink 封装为一个隐藏元素:
struct HiddenNavigationLink<Content: View>: View {
var destination: Content
@Binding var activateLink: Bool
var body: some View {
NavigationLink(destination: destination, isActive: self.$activateLink) {
EmptyView()
}
.frame(width: 0, height: 0)
.disabled(true)
.hidden()
}
}
Run Code Online (Sandbox Code Playgroud)
然后您可以在 NavigationView 中使用它(这很重要)并从导航栏中的 Button 触发它:
VStack {
HiddenNavigationList(destination: SearchView(), activateLink: self.$searchActivated)
...
}
.navigationBarItems(trailing:
Button("Search") { self.searchActivated = true }
)
Run Code Online (Sandbox Code Playgroud)
将其包装在“//HACK”注释中,以便在 Apple 修复此问题时您可以替换它。
| 归档时间: |
|
| 查看次数: |
1814 次 |
| 最近记录: |