From 7d89a9d3ee041106c58e547feeeeb7c3dabfb3c6 Mon Sep 17 00:00:00 2001 From: joywayer Date: Wed, 24 Jun 2026 02:05:25 +0800 Subject: [PATCH] =?UTF-8?q?3.E=20=E4=BF=AE=E5=A4=8D=EF=BC=9A=E6=8D=A2?= =?UTF-8?q?=E7=94=A8=20iOS=2017+=20AVAudioApplication.requestRecordPermiss?= =?UTF-8?q?ion=20=E9=81=BF=E5=85=8D=20EXC=5FBREAKPOINT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题 第一次调用 prepareaudio 弹出系统权限对话框,用户点允许/拒绝都触发 Thread 10 EXC_BREAKPOINT 崩溃。 ## 根因猜测 deprecated 的 AVAudioSession.requestRecordPermission(_:) 在 iOS 26.5 SDK 上内部桥接到 AVAudioApplication 时,与 withCheckedContinuation 的 Swift Concurrency 状态机交互异常。 具体表现:completion 在 Thread 10 触发 cont.resume(returning:), runtime 检测到某种 actor / continuation 状态违规,触发 trap。 ## 修复 新增 `requestMicrophonePermission()` 私有助手: ```swift if #available(iOS 17.0, *) { return await AVAudioApplication.requestRecordPermission() // 原生 async } else { return await withCheckedContinuation { ... } // 旧 SDK 兼容 } ``` iOS 17+ 走原生 async API,不经 Continuation 状态机,避开 corner case; iOS 15.6 / 16 走 deprecated API 兼容路径。 ## 验证 BuildProject 通过 0 错误。真机首次启动 → 按录音按钮 → 系统权限对话框 出现 → 点允许/拒绝 → 应无崩溃。 --- .../Bridge/Handlers/RemoteAudioHandler.swift | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift b/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift index 3432ba8..2f2f50c 100644 --- a/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift +++ b/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift @@ -101,11 +101,13 @@ public enum RemoteAudioHandler { // 首次启动:弹系统权限对话框,**不**启动录音浮层(避免与 touchObserver // 死锁——touchObserver 会捕获用户松手点"允许"的动作立刻 stop 录音)。 // 用户做完选择 / 第二次按录音按钮时走 .authorized 分支正常录音。 - _ = await withCheckedContinuation { cont in - AVAudioSession.sharedInstance().requestRecordPermission { granted in - cont.resume(returning: granted) - } - } + // + // 优先用 iOS 17+ 的 AVAudioApplication.requestRecordPermission() + // (原生 async,Swift Concurrency 一等公民);iOS 26+ 上 + // deprecated 的 AVAudioSession.requestRecordPermission(_:) + + // withCheckedContinuation 桥接路径实测会触发 Thread 10 + // EXC_BREAKPOINT(疑似系统内部桥接新 API 时状态机异常)。 + _ = await requestMicrophonePermission() // ⚠️ 必须触发 cb(对齐 daoqi ifauth==1 路径行为,daoqi NewRootVC.m:322 // 在 [recorderVC beginRecordByFileName:] 后总是 responseCallback)。 // @@ -336,6 +338,29 @@ public enum RemoteAudioHandler { callback?(.string("Response from mediaTypeAudio")) } + /// 麦克风权限请求(弹系统对话框)。 + /// + /// iOS 17+ 用新 `AVAudioApplication.requestRecordPermission()`(原生 async); + /// iOS 15.6 / 16 用 deprecated 的 `AVAudioSession.requestRecordPermission(_:)` + + /// withCheckedContinuation 桥接。 + /// + /// **不用** deprecated API 走新 SDK 路径的原因:实测 iOS 26.5 SDK 上 deprecated + /// API 内部桥接到 AVAudioApplication 时与 withCheckedContinuation 的状态机交互 + /// 异常,会在 Thread 10 触发 EXC_BREAKPOINT(疑似系统 bug 或 Swift Concurrency + /// 与 ObjC 桥接的 corner case)。新 API 直接 await 不经 Continuation 状态机, + /// 行为稳定。 + private static func requestMicrophonePermission() async -> Bool { + if #available(iOS 17.0, *) { + return await AVAudioApplication.requestRecordPermission() + } else { + return await withCheckedContinuation { (cont: CheckedContinuation) in + AVAudioSession.sharedInstance().requestRecordPermission { granted in + cont.resume(returning: granted) + } + } + } + } + @MainActor private static func showMicrophonePermissionAlert(on hostVC: UIViewController?) { // 用户已拒绝麦克风权限时调用。iOS 不允许再次主动弹系统权限对话框