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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:39:21