Swift开发:如何在App内添加按钮停止ReplayKit广播(无需通知中心)
在App内添加按钮直接停止屏幕广播的实现方案
当然可行!其实通过 ReplayKit 提供的 API,我们完全可以在App内添加一个自定义按钮,直接触发停止广播的操作,不用让用户跳去通知中心。下面给你具体的实现思路和代码修改方案:
核心思路
我们可以通过 RPSystemBroadcastPickerView 关联你的广播扩展,然后获取到活跃的 RPBroadcastSession 对象——这个对象是控制广播生命周期的核心,调用它的 finishBroadcast() 方法就能直接停止广播。
具体实现步骤与代码修改
1. 准备自定义停止按钮
在你的视图控制器里添加一个按钮,初始隐藏,当广播启动后显示出来。
2. 获取广播会话引用
通过 RPBroadcastActivityViewController 的代理方法,在用户选择并启动广播后,拿到当前的广播会话。
3. 实现停止广播的逻辑
给停止按钮添加点击事件,调用会话的停止方法,并处理状态回调。
修改后的完整代码如下:
import ReplayKit class YourViewController: UIViewController, RPBroadcastActivityViewControllerDelegate { // 保存当前广播会话的引用 private var broadcastSession: RPBroadcastSession? // 自定义停止广播按钮 private lazy var stopBroadcastButton: UIButton = { let btn = UIButton(type: .system) btn.setTitle("停止广播", for: .normal) btn.titleLabel?.font = UIFont.systemFont(ofSize: 14) btn.addTarget(self, action: #selector(stopBroadcastTapped), for: .touchUpInside) btn.isHidden = true // 调整按钮位置,放在picker下方 btn.frame = CGRect(x: (holderVw.frame.width / 2) - 45, y: 42, width: 90, height: 30) return btn }() override func viewDidLoad() { super.viewDidLoad() UIScreen.main.addObserver(self, forKeyPath: "captured", options: .new, context: nil) addRPkitVw() // 把停止按钮添加到holderVw中 holderVw.addSubview(stopBroadcastButton) } func addRPkitVw() { let broadcastPickerView = RPSystemBroadcastPickerView(frame: CGRect(x: (holderVw.frame.width / 2) - 19, y: 0, width: 38, height: 38)) holderVw.addSubview(broadcastPickerView) broadcastPickerView.backgroundColor = .clear broadcastPickerView.showsMicrophoneButton = true // 替换成你自己的广播扩展Bundle ID! broadcastPickerView.preferredExtension = "com.yourapp.your-broadcast-extension" // 替换picker内部按钮的点击事件,以便我们自己处理广播控制器的展示 if let internalButton = broadcastPickerView.subviews.first as? UIButton { internalButton.removeTarget(nil, action: nil, for: .allEvents) internalButton.addTarget(self, action: #selector(presentBroadcastPicker), for: .touchUpInside) } } @objc private func presentBroadcastPicker() { guard let pickerViewController = broadcastPickerViewController else { return } pickerViewController.delegate = self present(pickerViewController, animated: true) } // 实现代理方法,拿到启动后的广播会话 func broadcastActivityViewController(_ broadcastActivityViewController: RPBroadcastActivityViewController, didFinishWith broadcastSession: RPBroadcastSession?) { self.broadcastSession = broadcastSession stopBroadcastButton.isHidden = false // 显示停止按钮 broadcastActivityViewController.dismiss(animated: true) } // 停止广播的点击事件 @objc private func stopBroadcastTapped() { guard let session = broadcastSession else { return } session.finishBroadcast { [weak self] error in guard let self = self else { return } if let error = error { print("停止广播失败:\(error.localizedDescription)") } else { print("广播已成功停止") self.stopBroadcastButton.isHidden = true self.broadcastSession = nil } } } // 监听屏幕捕获状态,处理异常情况(比如用户手动在通知中心停止) override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "captured" { let isCaptured = change?[.newKey] as? Bool ?? false if !isCaptured { stopBroadcastButton.isHidden = true broadcastSession = nil } } } deinit { UIScreen.main.removeObserver(self, forKeyPath: "captured") } }
注意事项
- 替换Bundle ID:一定要把代码里的
com.yourapp.your-broadcast-extension替换成你实际的广播扩展的Bundle ID,这个可以在Xcode的扩展Target的「General」标签页里找到。 - 状态同步:监听
UIScreen的captured属性是为了处理用户在通知中心手动停止广播的情况,保证App内的按钮状态和实际广播状态同步。 - 权限问题:确保你的广播扩展已经正确配置,并且App已经获取了屏幕录制的权限。
内容的提问来源于stack exchange,提问作者MidDev
相关产品推荐
相关产品推荐

