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

Firebase登出后重登录,点击播放按钮App无响应冻结

问题分析与解决方案

看起来你遇到了一个典型的状态残留或资源未正确释放导致的主线程阻塞问题,我来帮你拆解下可能的原因和解决方向:

1. 登出流程未彻底清理播放相关资源

登出后直接跳转登录页,但播放模块的核心对象(比如播放器实例、音频会话、通知观察者)可能还留在内存中,重新登录后新的播放实例和旧残留资源冲突,最终导致App冻结。

建议优化登出逻辑:在登出时主动清理所有播放相关资源:

func handleLogout() {
    // 停止播放并销毁播放器实例
    player?.stop()
    player = nil
    
    // 移除所有相关通知观察者
    NotificationCenter.default.removeObserver(self)
    
    // 重置音频会话状态
    do {
        try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    } catch {
        print("音频会话关闭失败: \(error)")
    }
    
    // 跳转登录页(建议替换成你的跳转逻辑)
    let loginVC = LoginViewController()
    UIApplication.shared.keyWindow?.rootViewController = loginVC
}

2. 播放按钮的状态/逻辑存在残留绑定

从你给出的代码片段来看,你在处理logoutBtn的交互状态,可能登录流程完成后,播放按钮的事件绑定、状态初始化没有完全重置,导致点击时触发了旧的异常逻辑,阻塞主线程。

建议检查:

  • 确保登录完成后,重新初始化播放按钮的点击事件、状态(比如isEnabled、关联的业务逻辑)
  • 所有播放前的耗时操作(如音频文件加载、资源解析)必须放到后台线程,主线程只处理UI更新:
@objc func playButtonTapped() {
    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        guard let self = self else { return }
        // 后台执行耗时的播放准备操作
        self.prepareAudioResource()
        
        DispatchQueue.main.async {
            // 回到主线程启动播放
            self.player?.play()
        }
    }
}

3. 排查内存循环引用

如果播放器或相关业务对象和ViewController形成了循环引用,登出后这些对象无法被释放,重新登录后内存中存在多个冲突实例,最终引发卡死。

建议操作:

  • 检查所有闭包、代理是否使用了weak self避免循环引用,比如播放器回调:
player?.playStateChanged = { [weak self] state in
    guard let self = self else { return }
    // 处理播放状态变化逻辑
}
  • 使用Xcode的Memory Graph Debugger查看内存中是否有未释放的播放相关对象。

4. 定位主线程阻塞点

App无报错冻结大概率是主线程被阻塞,你可以用Xcode的调试工具快速定位:

  1. 当App冻结时,点击Xcode工具栏的Pause按钮
  2. 在左侧调试导航栏查看Main Thread的调用栈,找到卡住的具体代码行,这会帮你精准定位问题根源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:12:29