SwiftUI:NavigationView/NavigationLink:启动并推送目的地?
Posted
技术标签:
【中文标题】SwiftUI:NavigationView/NavigationLink:启动并推送目的地?【英文标题】:SwiftUI: NavigationView/NavigationLink: launch with destination pushed? 【发布时间】:2021-05-29 09:16:05 【问题描述】:ios Mail 应用启动时,您最近查看的邮箱已被推送到导航堆栈,即使它实际上是一个详细信息屏幕,并且根视图控制器是所有邮箱的列表。这在 UIKit 中是微不足道的,因为推送到导航控制器是微不足道的,并且可以在 viewDidLoad 或 applicationDidFinishLaunching 内部完成。
NavigationView 和 NavigationLink 是用于在 SwiftUI 中执行导航推送/弹出的 API,NavigationLink 支持几个模仿编程导航的 API - 但我不太清楚如何支持这个特定的用例。每次屏幕出现时都会调用onAppear
闭包(更像viewDidAppear
而不是viewDidLoad
),因此设置与 NavigationLink 对应的 selection
值将导致在用户尝试弹出时重复推送该详细信息屏幕。我可以尝试对维护State
进行一些修改,以了解屏幕是否已被新查看,但这似乎并不理想。 (关于 NavigationLink 的 selection
API 不稳定,我也遇到了一些问题,但这可能是一个单独的问题。)
有什么建议吗?如何在详细信息屏幕上启动应用程序,但在没有任何程序干预的情况下让 NavigationView 正常运行?
【问题讨论】:
【参考方案1】:如果您不需要以模式或动画的形式呈现您的视图,您应该使用编程导航(NavigationLink
with selection binding)来获得所需的行为。
例如,如果它是您的应用程序的根目录,则以下内容应该有效:
struct Item: Identifiable
let id: Int
let name: String
struct NormalNav: View
@State var items: [Item] = [
.init(id: 0, name: "One"),
.init(id: 1, name: "Two"),
.init(id: 2, name: "Three")
]
@State private var selection: Int? = 1
var body: some View
NavigationView
List
ForEach(items) item in
NavigationLink(item.name,
destination: Text(item.name),
tag: item.id,
selection: $selection)
上面的视图应该直接打开到第二个项目(“Two”),没有动画。
但是,有一个皱纹。如果您需要在 Sheet 中显示此视图,则会使用动画推送详细视图,这可能不是您想要的。
在this answer 的基础上,您可以在初始创建时抑制动画,但在后续导航时将其重新打开:
struct ContentView: View
@State var items: [Item] = [
.init(id: 0, name: "One"),
.init(id: 1, name: "Two"),
.init(id: 2, name: "Three")
]
@State private var selection: Int? = nil
@State var isAnimationDisabled = true
@State var isListPresented = false
var body: some View
Button("Show list")
isListPresented = true
.sheet(isPresented: $isListPresented)
NavigationView
List
ForEach(items) item in
NavigationLink(item.name,
destination: Text(item.name),
tag: item.id,
selection: $selection)
.animations(disabled: isAnimationDisabled)
.onChange(of: selection) value in
if value == nil
isAnimationDisabled = false
.onAppear
selection = 1
extension View
func animations(disabled: Bool) -> some View
transaction (tx: inout Transaction) in
guard disabled else
return
tx.disablesAnimations = true
tx.animation = .none
【讨论】:
谢谢 - 我在你给我的第一个例子中使用了同样的方法(使用标签和选择的 NavigationLink)并且遇到了问题,但我会再看看我自己的代码现在我有一个工作简化的例子。以上是关于SwiftUI:NavigationView/NavigationLink:启动并推送目的地?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI NavigationLink 如何到达另一个 SwiftUI 页面?
SwiftUI - 如何在 SwiftUI 中弹出到特定视图?