You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中@FocusState导致NavigationLink触发两次的问题

解决NavigationLink触发两次、目标视图重复初始化的问题

问题根源

点击NavigationLink时,系统会自动移除TextField的焦点,导致@FocusState var focussed的值更新,触发ContentView的body重新计算。此时isActive已经为true,body重绘时会重新创建NavigationLink,连带其destination的MyViewTwo再次执行init方法。

解决方案

1. 使用LazyView延迟目标视图初始化

自定义一个LazyView,让目标视图只有在真正被导航到的时候才会初始化,避免父视图重绘时重复创建:

struct LazyView<Content: View>: View {
    let build: () -> Content
    init(_ build: @autoclosure @escaping () -> Content) {
        self.build = build
    }
    var body: some View {
        build()
    }
}

// 修改ContentView中的NavigationLink
NavigationLink("Tap Me", destination: LazyView(MyViewTwo()), isActive: $isActive)

即使body重绘,LazyView也不会立即创建MyViewTwo,只有导航触发时才会执行init。

2. 手动控制焦点与导航触发

在点击导航按钮时主动取消焦点,避免后续FocusState变化触发的重绘影响:

// 把NavigationLink换成Button + 手动控制isActive
Button("Tap Me") {
    focussed = false // 主动取消焦点
    isActive = true
}
.navigationDestination(isPresented: $isActive) {
    MyViewTwo()
}

用Button触发导航,提前取消焦点,避免FocusState的变化导致body重绘时重复触发导航逻辑。

3. 改用iOS 16+的NavigationStack(推荐)

如果项目支持iOS 16及以上,使用NavigationStack配合navigationDestination修饰符,这种API的视图生命周期更稳定,不会因为父视图重绘而重复初始化目标视图:

struct ContentView: View {
    @State var text: String = "text"
    @FocusState var focussed: Bool
    @State var isActive: Bool = false

    var body: some View {
        NavigationStack { // 替换NavigationView为NavigationStack
            List {
                TextField("", text: $text)
                    .focused($focussed)
                    .onChange(of: focussed) { _ in }
                
                let _ = Self._printChanges()
                NavigationLink("Tap Me", isActive: $isActive) {
                    EmptyView() // 这里用EmptyView占位
                }
            }
            .navigationDestination(isPresented: $isActive) {
                MyViewTwo() // 目标视图在这里声明
            }
        }
    }
}

navigationDestination会独立管理目标视图的创建,父视图body重绘不会影响它,自然不会重复调用init。


内容的提问来源于stack exchange,提问作者Ash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:10:28