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

SwiftUI应用从Deep Link返回时触发NSInvalidArgumentException问题排查

SwiftUI模态Sheet重复弹出崩溃问题排查

错误信息

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally a view controller <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x13000c800> that is already being presented by <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier: 0x130822e00>.'

触发时机:从Deep Link返回应用时触发。

代码逻辑

  1. App入口解析Deep Link后发送通知:
NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: token.notify), object: nil, userInfo: ["token":token.token]))
  1. MainTabView中接收通知并处理:
.onReceive(pubTokenReceived, perform: { notification in
                timer?.invalidate()
                if let userInfo = notification.userInfo {
                    receivedToken = userInfo["token"] as! String
                    print (receivedToken)
                        if (token == receivedToken) {
                            let tan = Slt.get6DigitRandomNumberString()

                            print ("TAN: " + tan)
                            slt.sendSMSforIdentificationTo(email: email, tan: tan)
                            firstResponder = .tan
                            timeOrTryCounter = 3
                            sheetId = MainTabViewSheetId(id: .identificationStep2)
                    }
                }
            })

崩溃触发点:执行到sheetId = MainTabViewSheetId(id: .identificationStep2)时触发错误,sheetId是MainTabView的@State变量,用于控制模态Sheet的显示。

排查思路

  • 检查Sheet当前状态:崩溃核心是重复弹出已显示的模态视图。在设置sheetId前增加判断,若当前sheetId已经是.identificationStep2,则跳过赋值操作,避免重复触发。
  • 排查通知重复发送:Deep Link唤醒App时,可能因系统回调机制导致通知被多次触发。可以在发送通知时添加日志标记,或者给通知增加唯一标识,过滤重复的通知回调。
  • 强制在主线程执行UI操作:通知回调可能在非主线程触发,而SwiftUI的UI更新必须在主线程完成。将设置sheetId的代码包裹在主线程异步块中:
DispatchQueue.main.async {
    sheetId = MainTabViewSheetId(id: .identificationStep2)
}
  • 规范Sheet呈现逻辑:确保使用.sheet(item: $sheetId)这种基于唯一标识的呈现方式,避免同时存在多个.sheet修饰符导致视图层级冲突。
  • 延迟执行Sheet弹出:从Deep Link返回时,App可能处于后台唤醒的视图层级恢复阶段,此时直接弹出Sheet容易引发冲突。可以延迟执行弹出操作,比如:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    sheetId = MainTabViewSheetId(id: .identificationStep2)
}
  • 修复强制解包风险:代码中receivedToken = userInfo["token"] as! String使用了强制解包,虽不是当前崩溃原因,但建议改为可选绑定,避免后续出现其他崩溃问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:35:15