diff --git a/Sources/PlayerBridge.swift b/Sources/PlayerBridge.swift index 83ba4ba..94396bb 100644 --- a/Sources/PlayerBridge.swift +++ b/Sources/PlayerBridge.swift @@ -178,10 +178,10 @@ final class PlayerBridge: ObservableObject { #if os(iOS) hlsRecorder.onRecordingSaved = { [weak self] url in - NSLog("[MiniPlayer] onRecordingSaved called, setting pendingExportURL: %@", url.lastPathComponent) + NSLog("[MiniPlayer] onRecordingSaved called: %@", url.lastPathComponent) self?.showToast("Saved: \(url.lastPathComponent)") - self?.pendingExportURL = url - NSLog("[MiniPlayer] pendingExportURL set to: %@", url.lastPathComponent) + // 直接用 UIKit present,不依赖 SwiftUI sheet binding + self?.presentShareSheet(for: url) } hlsRecorder.onError = { [weak self] msg in self?.showToast(msg) @@ -190,6 +190,26 @@ final class PlayerBridge: ObservableObject { } #if os(iOS) + /// 直接通过 UIKit present UIActivityViewController,绕过 SwiftUI sheet 可能的多 sheet 冲突 + func presentShareSheet(for url: URL) { + guard let windowScene = UIApplication.shared.connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .first(where: { $0.activationState == .foregroundActive }) + ?? UIApplication.shared.connectedScenes.compactMap({ $0 as? UIWindowScene }).first + else { return } + + var topVC = windowScene.keyWindow?.rootViewController + ?? windowScene.windows.first(where: { !$0.isHidden && $0.bounds.size != .zero })?.rootViewController + while let presented = topVC?.presentedViewController { topVC = presented } + + let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil) + activityVC.completionWithItemsHandler = { _, _, _, _ in + // 录制完成后可以删掉临时文件?不,用户可能需要再次分享 + } + topVC?.present(activityVC, animated: true) + NSLog("[MiniPlayer] presentShareSheet: presented for %@", url.lastPathComponent) + } + /// 配置 AVAudioSession,支持后台音频和 PiP private func ensureAudioSession() { let session = AVAudioSession.sharedInstance()