iOS应用后台SIGABRT崩溃:无法创建UIWindow弱引用
问题分析与解决方案
可能的崩溃原因
- 原窗口引用风险:在
showPrivacyProtectionWindow中通过self.window?.windowScene获取窗口场景时,原应用窗口(self.window)可能因系统内存回收、Scene状态变更等极端情况正在被释放。UIKit内部管理窗口时会对实例添加弱引用,若目标实例处于释放过程中,就会触发“无法创建弱引用”的SIGABRT错误。 - 生命周期不同步:隐私窗口的生命周期未与Scene完全绑定,当Scene即将销毁(如用户切换应用导致Scene被系统回收)时,隐私窗口未被及时清理,残留的引用会与系统资源回收流程冲突。
- 重复创建窗口:极端场景下系统可能重复调用
sceneDidEnterBackground,若未做判断会重复创建隐私窗口,导致多窗口引用混乱,增加释放时的冲突概率。
具体修复方案
1. 直接从Scene获取窗口场景,避免依赖原窗口
修改showPrivacyProtectionWindow中获取windowScene的逻辑,跳过对self.window的依赖,直接从SceneDelegate的scene属性获取,同时增加重复创建判断:
func showPrivacyProtectionWindow() { guard let windowScene = scene as? UIWindowScene else { return } // 避免重复创建隐私窗口 guard !privacyProtectionWindowVisible else { return } privacyProtectionWindowVisible = true privacyProtectionWindow = UIWindow(windowScene: windowScene) privacyProtectionWindow?.rootViewController = UIStoryboard(name: "Login", bundle: nil).instantiateInitialViewController() ?? UIViewController() privacyProtectionWindow?.windowLevel = .alert + 1 privacyProtectionWindow?.makeKeyAndVisible() }
2. 同步隐私窗口与Scene的生命周期
在SceneDelegate中实现sceneDidDisconnect方法,确保Scene销毁时主动清理隐私窗口:
func sceneDidDisconnect(_ scene: UIScene) { guard privacyProtectionWindowVisible else { return } privacyProtectionWindow?.alpha = 0 privacyProtectionWindow?.isHidden = true privacyProtectionWindow = nil privacyProtectionWindowVisible = false dismissedPrivacyProtectionWindow = true }
3. 优化隐私窗口的移除逻辑
在hidePrivacyProtectionWindow中增加窗口隐藏步骤,确保窗口先从界面移除再释放引用,同时增加完成状态判断:
func hidePrivacyProtectionWindow() { UIView.animate(withDuration: 0.3) { [weak self] in self?.privacyProtectionWindow?.alpha = 0 } completion: { [weak self] finish in guard let self = self, finish else { return } self.privacyProtectionWindow?.isHidden = true self.privacyProtectionWindow = nil self.privacyProtectionWindowVisible = false self.dismissedPrivacyProtectionWindow = true } }
4. 防止重复触发隐私窗口创建
在sceneDidEnterBackground中增加判断,仅当隐私窗口未显示时才调用创建方法:
func sceneDidEnterBackground(_ scene: UIScene) { if !privacyProtectionWindowVisible { showPrivacyProtectionWindow() } }
内容的提问来源于stack exchange,提问作者Simon McLoughlin
相关产品推荐
相关产品推荐

