import ReplayKit import UIKit /// ReplayKit 管理器 /// 负责管理屏幕广播的启动、停止和状态监控 class ReplayKitManager: NSObject { // MARK: - 单例 static let shared = ReplayKitManager() // MARK: - 属性 private var broadcastController: RPBroadcastController? private let appGroupIdentifier = "group.com.saitong.voitrans.shared" private var isRecording = false // 回调闭包 var onBroadcastStarted: (() -> Void)? var onBroadcastFinished: (() -> Void)? var onBroadcastError: ((Error) -> Void)? // MARK: - 初始化 private override init() { super.init() setupNotifications() } // MARK: - 公共方法 /// 启动屏幕广播 /// - Parameter completion: 完成回调 func startBroadcast(completion: @escaping (Bool, Error?) -> Void) { print("🎬 准备启动 ReplayKit 广播") // 检查是否已经在录制 if isRecording { print("⚠️ 广播已在进行中") completion(false, NSError(domain: "ReplayKitManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "广播已在进行中"])) return } // 获取广播选择器 RPBroadcastActivityViewController.load { [weak self] (broadcastActivityViewController, error) in DispatchQueue.main.async { guard let self = self else { return } if let error = error { print("❌ 加载广播选择器失败: \(error.localizedDescription)") completion(false, error) return } guard let broadcastActivityViewController = broadcastActivityViewController else { let error = NSError(domain: "ReplayKitManager", code: -2, userInfo: [NSLocalizedDescriptionKey: "无法加载广播选择器"]) completion(false, error) return } // 设置代理 broadcastActivityViewController.delegate = self // 显示广播选择器 if let topViewController = self.getTopViewController() { broadcastActivityViewController.modalPresentationStyle = .formSheet topViewController.present(broadcastActivityViewController, animated: true) { print("✅ 广播选择器已显示") completion(true, nil) } } else { let error = NSError(domain: "ReplayKitManager", code: -3, userInfo: [NSLocalizedDescriptionKey: "无法获取顶层视图控制器"]) completion(false, error) } } } } /// 停止屏幕广播 /// - Parameter completion: 完成回调 func stopBroadcast(completion: @escaping (Bool, Error?) -> Void) { print("🛑 准备停止 ReplayKit 广播") guard isRecording else { print("⚠️ 当前没有进行中的广播") completion(false, NSError(domain: "ReplayKitManager", code: -4, userInfo: [NSLocalizedDescriptionKey: "当前没有进行中的广播"])) return } broadcastController?.finishBroadcast { [weak self] error in DispatchQueue.main.async { if let error = error { print("❌ 停止广播失败: \(error.localizedDescription)") completion(false, error) } else { print("✅ 广播已停止") self?.isRecording = false self?.broadcastController = nil completion(true, nil) } } } } /// 更新字幕内容 /// - Parameters: /// - text: 字幕文本 /// - sourceLanguage: 源语言 /// - targetLanguage: 目标语言 /// - isIntermediate: 是否为中间结果 func updateSubtitle(text: String, sourceLanguage: String = "", targetLanguage: String = "", isIntermediate: Bool = false) { guard let userDefaults = UserDefaults(suiteName: appGroupIdentifier) else { print("❌ 无法访问 App Group UserDefaults") return } // 更新字幕数据 userDefaults.set(text, forKey: "subtitle_text") userDefaults.set(sourceLanguage, forKey: "subtitle_source_language") userDefaults.set(targetLanguage, forKey: "subtitle_target_language") userDefaults.set(isIntermediate, forKey: "subtitle_is_intermediate") userDefaults.set(Date().timeIntervalSince1970, forKey: "subtitle_timestamp") // 强制同步 userDefaults.synchronize() print("📝 字幕已更新: \(text)") } /// 检查广播状态 var isBroadcasting: Bool { return isRecording } // MARK: - 私有方法 /// 设置通知监听 private func setupNotifications() { NotificationCenter.default.addObserver( self, selector: #selector(applicationDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(applicationWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil ) } /// 应用进入后台 @objc private func applicationDidEnterBackground() { print("📱 应用进入后台,广播状态: \(isRecording)") } /// 应用即将进入前台 @objc private func applicationWillEnterForeground() { print("📱 应用即将进入前台,广播状态: \(isRecording)") } /// 获取顶层视图控制器 private func getTopViewController() -> UIViewController? { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first else { return nil } var topViewController = window.rootViewController while let presentedViewController = topViewController?.presentedViewController { topViewController = presentedViewController } return topViewController } // MARK: - 清理 deinit { NotificationCenter.default.removeObserver(self) print("🗑️ ReplayKitManager 已清理") } } // MARK: - RPBroadcastActivityViewControllerDelegate extension ReplayKitManager: RPBroadcastActivityViewControllerDelegate { func broadcastActivityViewController(_ broadcastActivityViewController: RPBroadcastActivityViewController, didFinishWith broadcastController: RPBroadcastController?, error: Error?) { DispatchQueue.main.async { [weak self] in // 关闭选择器 broadcastActivityViewController.dismiss(animated: true) if let error = error { print("❌ 广播设置失败: \(error.localizedDescription)") self?.onBroadcastError?(error) return } guard let broadcastController = broadcastController else { print("❌ 无法获取广播控制器") let error = NSError(domain: "ReplayKitManager", code: -5, userInfo: [NSLocalizedDescriptionKey: "无法获取广播控制器"]) self?.onBroadcastError?(error) return } // 保存广播控制器 self?.broadcastController = broadcastController broadcastController.delegate = self // 开始广播 broadcastController.startBroadcast { error in DispatchQueue.main.async { if let error = error { print("❌ 开始广播失败: \(error.localizedDescription)") self?.onBroadcastError?(error) } else { print("✅ 广播已开始") self?.isRecording = true self?.onBroadcastStarted?() } } } } } } // MARK: - RPBroadcastControllerDelegate extension ReplayKitManager: RPBroadcastControllerDelegate { func broadcastController(_ broadcastController: RPBroadcastController, didFinishWithError error: Error?) { DispatchQueue.main.async { [weak self] in self?.isRecording = false self?.broadcastController = nil if let error = error { print("❌ 广播结束时发生错误: \(error.localizedDescription)") self?.onBroadcastError?(error) } else { print("✅ 广播正常结束") self?.onBroadcastFinished?() } } } func broadcastController(_ broadcastController: RPBroadcastController, didUpdateServiceInfo serviceInfo: [String : NSCoding & NSObjectProtocol]) { print("📊 广播服务信息更新: \(serviceInfo)") } }