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

iOS 18中SwiftUI使用@Environment(\.dismiss)导致导航触发重复问题

iOS 18 SwiftUI导航中@Environment(.dismiss)导致视图重复加载问题

问题概述

在iOS 18的SwiftUI导航场景中,当目标视图(DetailView)引用@Environment(\.dismiss)时,导航至该视图会触发视图的body代码执行两次,表现为导航行为重复。

基础代码示例

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationStack {
            NavigationLink("Go to Detail View", destination: DetailView())
                .padding()
        }
    }
}

struct DetailView: View {
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        VStack {
            let _ = print("DetailView") // iOS 18中会被触发两次
        }
    }
}

问题现象

  • iOS 18环境下,只要DetailView中存在@Environment(\.dismiss),print("DetailView")会被执行两次;
  • 相同代码在iOS 17及更早版本中运行正常,仅触发一次打印;
  • 移除DetailView中的@Environment(\.dismiss)后,iOS 18中打印仅触发一次,导航行为恢复正常。

替代导航方案测试结果

使用.navigationDestination(for:)的导航方式,问题依然存在:

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("Mint", value: Color.mint)
                NavigationLink("Pink", value: Color.pink)
                NavigationLink("Teal", value: Color.teal)
            }
            .navigationDestination(for: Color.self) { _ in
                DetailView()
            }
            .navigationTitle("Colors")
        }
    }
}

iOS 18中DetailView的body仍会被执行两次,打印语句触发两次。

已尝试的解决方法

  • 移除@Environment(\.dismiss)可直接解决问题,iOS 18中视图加载恢复正常;
  • 确认问题仅与@Environment(\.dismiss)的使用相关,iOS 17及以下版本无此异常。

问题咨询

  1. 这是iOS 18与SwiftUI导航的已知问题吗?@Environment(\.dismiss)是否存在新的交互逻辑?
  2. 其他开发者是否遇到类似问题,iOS 18中的推荐处理方式是什么?
  3. 有没有可行的临时解决方案,确保使用@Environment(\.dismiss)时视图不会重复加载?

解决方案建议

  1. 确认问题属性:目前已有大量开发者在技术社区反馈该问题,属于iOS 18 Beta版本的SwiftUI导航栈兼容性Bug,Apple大概率会在后续Beta更新中修复。
  2. 临时Workaround:
    • 将副作用代码(如打印、网络请求、状态初始化等)移至onAppear回调中,避免在body中执行:
      struct DetailView: View {
          @Environment(\.dismiss) var dismiss
          
          var body: some View {
              VStack {}
              .onAppear {
                  print("DetailView appeared") // 仅触发一次
              }
          }
      }
      
    • 若必须在body中处理逻辑,可通过状态变量控制代码执行次数:
      struct DetailView: View {
          @Environment(\.dismiss) var dismiss
          @State private var hasExecuted = false
          
          var body: some View {
              VStack {
                  if !hasExecuted {
                      let _ = print("DetailView")
                      hasExecuted = true
                  }
              }
          }
      }
      
  3. 官方反馈:通过Apple的Feedback Assistant提交问题报告,附上代码示例和现象描述,帮助官方加速修复进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:05:16