SwiftUI NavigationLink 自行弹出

Jan*_*Jan 7 swiftui swiftui-navigationlink

我有一个简单的用例,其中一个屏幕使用NavigationLink. iOS 14.5 beta (1, 2, 3) 有一个奇怪的行为,推送的屏幕在被推送后就弹出。

我设法创建了一个示例应用程序,并在其中重现它。我相信原因是存在@Environment(\.presentationMode)似乎重新创建视图并导致弹出视图的原因。

完全相同的 cod 在 Xcode 12 / iOS 14.4 中运行良好

在此处输入图片说明

这是一个示例代码。

import SwiftUI

public struct FirstScreen: View {
    public init() {}
    public var body: some View {
        NavigationView {
            List {
                row
                row
                row
            }
        }
    }
    private var row: some View {
        NavigationLink(destination: SecondScreen()) {
            Text("Row")
        }
    }
}

struct SecondScreen: View {

    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    public var body: some View {
        VStack(spacing: 10) {
            NavigationLink(destination: thirdScreenA) {
                Text("Link to Third Screen A")
            }

            NavigationLink(destination: thirdScreenB) {
                Text("Link to Third Screen B")
            }

            Button("Go back", action: { presentationMode.wrappedValue.dismiss() })
        }

    }

    var thirdScreenA: some View {
        Text("thirdScreenA")
    }

    var thirdScreenB: some View {
        Text("thirdScreenB")
    }
}


struct FirstScreen_Previews: PreviewProvider {
    static var previews: some View {
        FirstScreen()
    }
}
Run Code Online (Sandbox Code Playgroud)

Jac*_*ack 38

我刚刚添加.navigationViewStyle(StackNavigationViewStyle())&错误消失了

例子 : -

 NavigationView {
         content
}
.navigationViewStyle(StackNavigationViewStyle())
Run Code Online (Sandbox Code Playgroud)

  • 我只花了 4 个小时来解决这个 bug。这是唯一有效的解决方法...... (5认同)
  • 这是 2021 年 12 月 1 日之前唯一可行的解​​决方案 (2认同)

Pau*_*sky 14

当恰好有 2 个 NavigationLinks 时,这看起来像是一个错误。如果您添加另一个空链接,它就会消失:

NavigationLink(destination: EmptyView(), label: {})
Run Code Online (Sandbox Code Playgroud)

更多详情:https : //forums.swift.org/t/14-5-beta3-navigationlink-unexpected-pop/45279

  • 似乎不再适用于 iOS 15 (20认同)
  • @coopersita 我在苹果开发者论坛上看到了你的评论。看来你面临着不同的问题。如果 DetailView 更新了 MasterView 上的 ForEach 列表中使用的数据,并导致 Master 重新渲染,则可能会导致弹出子视图层次结构。请提交另一个包含更多详细信息的问题 (4认同)
  • 可以确认最新的 iOS 15 版本(2021 年 11 月 9 日)上存在此不当行为 (3认同)

小智 10

正在申请.isDetailLink(false)您​​的 NavigationLink 可能会完成这项工作。默认情况下是 true。来自文档:

\n
\n

此方法设置在多列导航视图(如 DoubleColumnNavigationViewStyle)中使用导航链接时的行为。\n如果 isDetailLink 为 true,则在主列中执行链接\n会将辅助(详细)列的内容设置为链接\xe2\x80\x99s\n目标视图。如果 isDetailLink 为 false,链接将导航到\n主列中的目标视图。

\n
\n


Mar*_*ter 5

就我而言,我有:

(1) 带有根视图的选项卡视图有 2 个导航起点

(2) 第一个和第二个导航有相当多的嵌套视图

(3) 添加 .navigationViewStyle(StackNavigationViewStyle() 仅修复只有一个导航起点的根视图的问题

(4) 一旦我从同一视图进行另一个导航,问题就会再次出现(仅适用于 iOS 14.5 至 14.8)

(5) 单独添加

NavigationLink(destination: EmptyView()) {
    EmptyView()
}
Run Code Online (Sandbox Code Playgroud)

不适合我

(6) 在我的项目中,我有一个协调员负责创建 viewModel(已发布的属性),并且我有一个 ContainerView 来处理所有导航。导航链接是根据 viewModel 是否存在而创建的,因此如果 viewModel 存在,则将呈现该视图,并且当视图被关闭时,viewModel 将设置为 nil。(我将在最后添加执行此操作的代码)

(7) 由于某些奇怪的原因,向负责导航的视图添加第三个导航会停止我的容器视图重新渲染,并且视图停止弹出。

简单地将 NavigationLink 添加到容器中是行不通的,但是使用我正在使用的修改器并将目的地设置为空的 NavigationLink 却可以。

这是用于导航的代码:

    func navigation<Item, Destination: View>(
        item: Binding<Item?>,
        @ViewBuilder destination: (Item) -> Destination
    ) -> some View {
        let isActive = Binding(
            get: { item.wrappedValue != nil },
            set: { value in
                if !value {
                    item.wrappedValue = nil
                }
            }
        )
        return navigation(isActive: isActive) {
            item.wrappedValue.map(destination)
        }
    }

    func navigation<Destination: View>(
        isActive: Binding<Bool>,
        @ViewBuilder destination: () -> Destination
    ) -> some View {
        overlay(
            NavigationLink(
                destination: isActive.wrappedValue ? destination() : nil,
                isActive: isActive,
                label: { EmptyView() }
            )
        )
    }
Run Code Online (Sandbox Code Playgroud)

这就是我的容器视图的工作原理。我的协调器具有作为可选 viewModel 的 Published 属性,并且该 viewModel 是否存在将触发导航链接上的 isActive 值。添加最后一个 .navigation 有效。我的空容器只有空的 navigationLink

我的导航容器

  • @malhal 你为什么觉得这很奇怪?如何将导航与 SwiftUI 中的视图解耦?我不确定您是否有一个非常深的嵌套导航可以在 SwiftUI 中使用,但我的项目相当大,并且在视图内有导航链接,并且必须根据操作弹出到不同的视图,使用视图内的导航链接非常困难。 (2认同)