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

SwiftUI中在@Observable类访问自定义AppDelegate时遭遇类型转换崩溃的问题求助

SwiftUI中在@Observable类访问自定义AppDelegate时遭遇类型转换崩溃的问题求助

兄弟,我一眼就看出你踩了SwiftUI里@UIApplicationDelegateAdaptor的一个经典小坑!咱们先把问题根源捋清楚,再给你俩靠谱的解决办法。

你遇到的崩溃提示Could not cast value of type 'SwiftUI.AppDelegate' to 'MyApp.AppDelegate',本质原因是SwiftUI并没有把你自定义的AppDelegate直接设置为UIApplication的全局delegate。当你用@UIApplicationDelegateAdaptor的时候,SwiftUI会偷偷创建一个自己的内部AppDelegate代理类(就是错误里的SwiftUI.AppDelegate),然后把你的自定义Delegate作为子代理来调用生命周期方法——这就是为什么你能看到AppDelegate的打印语句,但强转的时候会崩溃:UIApplication.shared.delegate指向的是SwiftUI的内部类,不是你自己写的那个!

另外还要先纠正你代码里的一个小细节:你自定义的Delegate类叫CustomAppDelegate,但在@UIApplicationDelegateAdaptor里写的是AppDelegate.self,这会导致SwiftUI找不到你的自定义类,要么报错,要么自动生成一个默认的AppDelegate,这也会引发类型不匹配的问题。一定要确保@UIApplicationDelegateAdaptor里指定的类名和你自定义的Delegate类名完全一致!

接下来给你两个可行的解决办法:

方法一:通过依赖传递访问(符合SwiftUI设计理念)

这种方法是最贴合SwiftUI数据流转逻辑的,不用绕全局的UIApplication,直接把自定义AppDelegate传递给需要用到它的模型:

  1. 先修正MyApp里的Adaptor类名,把自定义Delegate传进ContentView:
@main
struct MyApp: App {
    // 这里要和你自定义的Delegate类名一致,比如你写的是CustomAppDelegate就用这个
    @UIApplicationDelegateAdaptor(CustomAppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView(appDelegate: appDelegate)
        }
    }
}
  1. 在ContentView里把AppDelegate传给你的MyModel:
struct ContentView: View {
    let appDelegate: CustomAppDelegate
    @State private var model: MyModel
    
    init(appDelegate: CustomAppDelegate) {
        self.appDelegate = appDelegate
        self._model = State(initialValue: MyModel(appDelegate: appDelegate))
    }
    
    var body: some View {
        // 你的视图内容
    }
}
  1. 修改MyModel,通过构造方法接收AppDelegate:
@MainActor @Observable class MyModel {
    private let appDelegate: CustomAppDelegate
    
    init(appDelegate: CustomAppDelegate) {
        self.appDelegate = appDelegate
    }
    
    func login() async {
        await withCheckedContinuation { continuation in
            appDelegate.currentAuthorizationFlow = OIDAuthState.authState()
            // 这里一定要调用resume()!你原来的代码漏了,不然异步任务会永远挂起
            continuation.resume()
        }
    }
}

方法二:给自定义AppDelegate加静态共享实例(全局访问)

如果你实在需要全局调用的方式,可以给自定义AppDelegate加一个静态共享实例,这样不用强转就能直接拿到:

  1. 修改你的CustomAppDelegate,添加静态shared属性并在启动时初始化:
class CustomAppDelegate: NSObject, UIApplicationDelegate {
    static var shared: CustomAppDelegate!
    var currentAuthorizationFlow: OIDExternalUserAgentSession?

    func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil ) -> Bool {
        print("AppDelegate: App has finished launching")
        // 把当前实例赋值给静态属性,方便全局调用
        CustomAppDelegate.shared = self
        return true
    }
}
  1. 然后在MyModel里直接用静态实例,完全不用碰UIApplication的delegate:
@MainActor @Observable class MyModel {
    func login() async {
        await withCheckedContinuation { continuation in
            CustomAppDelegate.shared.currentAuthorizationFlow = OIDAuthState.authState()
            // 同样别忘了调用resume()
            continuation.resume()
        }
    }
}

最后再提个醒:你原来的代码里withCheckedContinuation没有调用continuation.resume(),这会导致你的异步任务永远挂起,这个一定要补上,不然登录逻辑会直接卡死。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:43:01