AtomicXCore 的核心功能的集成指南,帮助开发者快速实现多人音视频房间功能。SDK 采用纯 API 架构设计,开发者可完全自定义 UI 界面,专注于业务逻辑和用户体验的实现。
RoomStore:房间管理功能入口,包含功能:预定房间、创建房间、加入房间、房间内呼叫等。RoomParticipantStore:房间内参与者功能入口, 包含功能:管理员设置、房主转移、移出房间、参与者设备控制等。RoomParticipantView:房间内参与者视频画面视图。sudo gem install cocoapods 命令进行安装。sudo gem install cocoapods 安装过程中可能需要输入电脑密码,按提示输入管理员密码即可。Podfile 文件中添加 pod 'AtomicXCore' 依赖。例如:target 'YourProjectTarget' do# 其他已有的 Pod 依赖...# 添加 pod 'AtomicXCore' 依赖pod 'AtomicXCore'end
cd 命令切换到您的 .xcodeproj 目录下,然后执行 pod init 命令创建 Podfile 文件,创建完成后,在您的 Podfile 文件中添加 pod 'AtomicXCore' 依赖。例如:# 如果您的项目目录是 /Users/yourusername/Projects/YourProject# 1. cd 到您的.xcodeproj工程目录下cd /Users/yourusername/Projects/YourProject# 2. 执行pod init,此命令运行完后,会在您的工程目录下生成一个 Podfile 文件。pod init# 3. 在生成的Podfile文件中添加pod 'AtomicXCore'依赖target 'YourProjectTarget' do# 添加pod 'AtomicXCore'依赖pod 'AtomicXCore'end
cd 到 Podfile 文件所在的目录,然后执行以下命令安装组件。pod install
Info.plist 文件中添加相机和麦克风的使用权限说明。<key>NSCameraUsageDescription</key><string>TUIRoomKit需要访问您的相机权限</string><key>NSMicrophoneUsageDescription</key><string>TUIRoomKit需要访问您的麦克风权限</string>

LoginStore.shared.login 完成登录,这是使用 AtomicXCore 所有功能的关键前提。import AtomicXCorefunc login() {LoginStore.shared.login(sdkAppID: 1400000001, // 替换为项目的 sdkAppIDuserID: "test_001", // 替换为项目的 userIDuserSig: "xxxxxxxxxxx") { result in // 替换为项目的 userSigswitch result {case .success(let info):debugPrint("login success")case .failure(let error):debugPrint("login failed code:\\(error.code), message:\\(error.message)")}}}
参数 | 类型 | 说明 |
sdkAppID | Int32 | |
userID | String | 当前用户的唯一 ID,仅包含英文字母、数字、连字符和下划线。为避免多端登录冲突,请勿使用 1、123 等简单 ID。 |
userSig | String | 用于腾讯云鉴权的票据。请注意: 开发环境:您可以采用本地 GenerateTestUserSig.genTestSig 函数生成 UserSig 或者通过 UserSig 辅助工具 生成临时的 UserSig。生产环境:为了防止密钥泄露,请务必采用服务端生成 UserSig 的方式。详细信息请参见 服务端生成 UserSig。 |

CreateRoomOptions 设置房间名称,房间密码。RoomStore 的 createAndJoinRoom 接口执行核心操作。import UIKitimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {// 初始化视图控制器并自动创建并加入房间逻辑public init(roomID: String, roomType: RoomType) {super.init(nibName: nil, bundle: nil)createAndJoinRoom(roomID: roomID, roomType: roomType)}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}// 调用此方法完成创建并加入房间的复合操作private func createAndJoinRoom(roomID: String, roomType: RoomType) {// 1. 配置房间初始化参数// CreateRoomOptions 用于定义房间的基础属性及初始权限控制var options = CreateRoomOptions()options.roomName = "我的讨论会" // 设置房间对外展示的名称options.password = "" // 设置房间进入密码(若无需密码则留空)// 2. 房间权限预设:在创建之初即可控制全场权限(通常用于正式会议场景)options.isAllCameraDisabled = false // 全员开启/禁用摄像头的初始状态options.isAllMessageDisabled = false // 全员开启/禁言的初始状态options.isAllMicrophoneDisabled = false // 全员开启/静音的初始状态options.isAllScreenShareDisabled = false // 全员禁止/允许屏幕分享的初始状态// 3. 创建并加入房间// 该方法是一个复合操作:若房间不存在则先创建,随后自动执行加入流程RoomStore.shared.createAndJoinRoom(roomID: roomID, roomType: roomType, options: options) { [weak self] result inguard let self = self else { return }switch result {case .success():print("创建并加入房间成功")case .failure(let error):print("创建并加入房间失败 [错误码: \\(error.code)]: \\(error.message)")}}}}
参数名 | 类型 | 必填 | 说明 |
roomID | String | 是 | 字符串类型的房间唯一标识符。 限制长度为 0-48 字节。 建议仅包含数字、英文字母(区分大小写)、下划线(_)和连字符(-)。避免使用空格和中文字符。 |
roomType | RoomType | 是 | 房间类型 standard:标准房间,所有成员可自由音视频互动。 webinar:大型研讨会房间,区分嘉宾和观众角色,观众默认无上麦权限。 |
options | CreateRoomOptions | 是 | 创建房间配置对象。 详细用法请参考:CreateRoomOptions 结构体详细说明。 |
completion | CompletionClosure | 否 | 操作完成回调,用于返回创建和加入房间的结果。若创建失败则会返回错误码和错误信息。 |
参数名 | 类型 | 必填 | 说明 |
roomName | String | 否 | 房间名称,可以不设置,默认为空字符串。 限制长度为 0-60 字节。 支持中英文、数字、特殊字符。 |
password | String | 否 | 房间密码,空字符串 "" 通常表示该房间不设密码。 限制长度为 0-32 字节。 推荐使用 4-8 位纯数字,方便移动端输入。设置后,其他用户加入房间时需输入密码。建议不要存储明文敏感信息。 |
isAllMicrophoneDisabled | Bool | 否 | 是否全员禁止打开麦克风。开启后,除房主/管理员外,普通参与者默认禁止打开麦克风。 true : 禁止。 false :取消禁止 (默认值)。 |
isAllCameraDisabled | Bool | 否 | 是否全员禁止打开摄像头。开启后,除房主/管理员外,普通参与者默认禁止打开摄像头。 true : 禁止。 false :取消禁止(默认值)。 |
isAllScreenShareDisabled | Bool | 否 | 是否全员禁止发起屏幕共享。开启后,仅房主/管理员可进行屏幕共享。 true : 禁止。 false :取消禁止(默认值)。 |
isAllMessageDisabled | Bool | 否 | 是否全员禁止发送聊天消息(禁言)。开启后,普通参与者无法在房间内发送文字消息。 true : 禁止。 false :取消禁言(默认值)。 |
DeviceStore 单例对象的 openLocalCamera、openLocalMicrophone 接口打开本地设备。import UIKitimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {private let roomID: Stringpublic init(roomID: String) {self.roomID = roomIDsuper.init(nibName: nil, bundle: nil)openDevices()}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}// 调用此方法打开设备private func openDevices() {// 1. 打开前置摄像头DeviceStore.shared.openLocalCamera(isFront: true, completion: nil)// 2. 打开麦克风DeviceStore.shared.openLocalMicrophone(completion: nil)}}
参数名 | 类型 | 必填 | 说明 |
isFront | Bool | 是 | 是否开启前置摄像头: true : 开启前置摄像头。 false :开启后置摄像头。 |
completion | CompletionClosure | 否 | 操作完成回调,用于返回开启摄像头的结果。若开启失败则会返回错误码和错误信息。 |
RoomStore 的 endRoom 接口即可结束当前房间。结束房间后,房间内的所有参与者都会收到房间结束事件。import UIKitimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {private let roomID: Stringpublic init(roomID: String) {self.roomID = roomIDsuper.init(nibName: nil, bundle: nil)endRoom()}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}/// 调用此方法结束房间private func endRoom() {// endRoom 接口用于永久结束当前房间。// 注意:通常该操作仅限房主(Owner)执行,执行后所有成员将被移出房间且音视频采集会强制停止。RoomStore.shared.endRoom { [weak self] result inguard let self = self else { return }switch result {case .success():print("结束房间成功")case .failure(let error):print("结束房间失败 [错误码: \\(error.code)]: \\(error.message)")}}}}

RoomStore 的 joinRoom 接口,即可加入房间,此时房间内其他参与者会收到参与者加入房间事件通知。import UIKitimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {public init(roomID: String, roomType: RoomType) {super.init(nibName: nil, bundle: nil)joinRoom(roomID: roomID, roomType: roomType)}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}/// 调用此方法加入一个已存在的房间private func joinRoom(roomID: String, roomType: RoomType) {// 1. 准备加入参数// joinRoom 适用于加入一个已知且正在进行的房间let targetRoomID = roomID // 目标房间 IDlet roomPassword = "" // 房间密码,若房间未设置密码则传空字符串或 nil// 2. 调用 RoomStore 加入房间接口// 该操作会验证房间是否存在、用户是否被禁入以及密码是否正确RoomStore.shared.joinRoom(roomID: targetRoomID, roomType: roomType, password: roomPassword) { [weak self] result inguard let self = self else { return }switch result {case .success():print("加入房间成功")case .failure(let error):print("加入房间失败 [错误码: \\(error.code)]: \\(error.message)")}}}}
参数名 | 类型 | 必填 | 说明 |
roomID | String | 是 | 字符串类型的房间唯一标识符。 限制长度为 0-48 字节。 建议仅包含数字、英文字母(区分大小写)、下划线(_)和连字符(-)。避免使用空格和中文字符。 |
roomType | RoomType | 是 | 房间类型: standard:标准房间,所有成员可自由音视频互动。 webinar:大型研讨会房间,区分嘉宾和观众角色,观众默认无上麦权限。 |
password | String | 是 | 房间密码,空字符串 "" 通常表示该房间不设密码。 限制长度为 0-32 字节。 推荐使用 4-8 位纯数字,方便移动端输入。设置后,其他用户加入房间时需输入密码。建议不要存储明文敏感信息。 |
completion | CompletionClosure | 否 | 操作完成回调,用于返回加入房间的结果。若加入房间失败则会返回错误码和错误信息。 |
RoomStore 的 leaveRoom 接口即可离开房间,此时房间内其他参与者都会收到参与者离开房间事件通知。import UIKitimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {private let roomID: Stringpublic init(roomID: String) {self.roomID = roomIDsuper.init(nibName: nil, bundle: nil)leaveRoom()}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}/// 调用此方法主动退出当前房间private func leaveRoom() {// 1. 业务逻辑说明// leaveRoom 接口用于普通成员或房主主动退出房间。// 与 endRoom 不同,房主调用 leaveRoom 只会让自己离开,房间依然存在。// 2. 调用 RoomStore 离开房间接口// 该操作会停止音视频流传输,并通知服务器将当前用户移出房间RoomStore.shared.leaveRoom { [weak self] result inguard let self = self else { return }switch result {case .success():print("退出房间成功")case .failure(let error):print("退出房间失败 [错误码: \\(error.code)]: \\(error.message)")}}}}
RoomParticipantView 组件为开发者提供了完整的视频画面渲染解决方案。该组件支持本地摄像头画面和远端参与者视频流的实时显示,集成过程简单高效。
RoomParticipantView 是用于渲染房间参与者视频流的核心视图组件,若需要更灵活的视频组件布局方式,请参考 TUIRoomKit 开源项目中 RoomView.swift 文件来了解完整的实现逻辑。RoomParticipantStore.state.participantList,建立参与者状态的响应式监听。participantList 状态数据。RoomParticipantView,绑定视频渲染逻辑。import UIKitimport Combineimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {private var participantStore: RoomParticipantStoreprivate var cancellableSet = Set<AnyCancellable>()private var views = [RoomParticipantView]()init(roomID: String) {// RoomParticipantStore 是与房间绑定的,需要通过 RoomParticipantStore.create(roomID: String) 工厂方法来为特定的房间创建实例participantStore = RoomParticipantStore.create(roomID: roomID)super.init(nibName: nil, bundle: nil)// 1. 数据层订阅subscribeParticipantState()participantStore.getParticipantList(cursor: "", completion: nil)}required init?(coder: NSCoder) { fatalError() }private func subscribeParticipantState() {participantStore.state.subscribe(StatePublisherSelector(keyPath: \\.participantList)).receive(on: DispatchQueue.main).sink { [weak self] participantList inguard let self = self else { return }// 2. 状态自动同步updateParticipantView(participantList)}.store(in: &cancellableSet)}private func updateParticipantView(_ list: [RoomParticipant]) {views.forEach { view inview.setActive(isActive: false)view.removeFromSuperview()}views = Array(list.prefix(9)).enumerated().map { index, participant in// 3. 视图初始化let participantView = RoomParticipantView(streamType: .camera, participant: participant)participantView.frame = CGRect(x: CGFloat(index % 3) * 125 + 10, y: CGFloat(index / 3) * 165 + 100, width: 120, height: 160)// 4. UI 集成view.addSubview(participantView)participantView.setActive(isActive: true)return participantView}}}
参数名 | 类型 | 必填 | 描述 |
streamType | VideoStreamType | 是 | 需要渲染视频流的类型: camera:摄像头流。 screen:屏幕分享流。 |
participant | RoomParticipant | 是 | 房间内实时的参与者对象,涵盖了从基础身份到业务状态、再到底层音视频设备权限的所有关键信息。 详细用法请参考:RoomParticipant 结构体详细说明。 |
参数名 | 类型 | 必填 | 说明 |
userID | String | 是 | 用户的唯一标识符。 |
userName | String | 否 | 用户的昵称。 |
avatarURL | String | 否 | 用户头像的 URL 地址。 |
nameCard | String | 否 | 用户在房间内的名片/备注名。 限制长度为 0-32 字节。 支持设置中英文、数字、特殊字符。 |
role | ParticipantRole | 否 | 房间参与者的成员角色。 owner:房主。 admin:管理员。 generalUser:普通用户(默认值)。 |
roomStatus | RoomParticipantStatus | 否 | 成员在房间中的业务状态。 scheduled:已预约(默认值)。 inCalling:呼叫中。 callTimeout:呼叫超时。 callRejected:拒绝呼叫。 inRoom:在房间中。 |
microphoneStatus | DeviceStatus | 否 | 麦克风设备的开启/关闭状态。 off:关闭(默认值)。 on:开启。 |
cameraStatus | DeviceStatus | 否 | 摄像头设备的开启/关闭状态。 off:关闭(默认值)。 on:开启。 |
screenShareStatus | DeviceStatus | 否 | 屏幕共享状态。 off:关闭(默认值)。 on:开启。 |
isMessageDisabled | Bool | 否 | 是否被禁言。为 true 时无法发送聊天消息。 true: 禁止。 false:取消禁止(默认值)。 |
metaData | [String: String] | 否 | 业务自定义扩展数据,随参与者状态同步。 限制长度为 0-60 字节。仅支持 JSON 类型字符串。 |
RoomStore 的 roomEventPublisher 可以订阅到 RoomEvent 中与房间相关的被动事件。import UIKitimport Combineimport AtomicXCore// RoomMainViewController 代表房间主视图控制器class RoomMainViewController: UIViewController {private let roomID: String// 用于存储 Combine 订阅关系,防止对象销毁导致监听失效private var cancellableSet = Set<AnyCancellable>()public init(roomID: String) {self.roomID = roomIDsuper.init(nibName: nil, bundle: nil)// 核心流程:在初始化时开启事件监听subscribeRoomEvents()}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}/// 调用此方法订阅房间被动事件private func subscribeRoomEvents() {// 1. 访问 RoomStore 的 roomEventPublisher// 该 Publisher 会推送房间全生命周期的事件,如呼叫、解散、预约提醒等RoomStore.shared.roomEventPublisher.receive(on: RunLoop.main) // 确保在主线程处理 UI 逻辑.sink { [weak self] event inguard let self = self else { return }// 2. 根据事件类型执行相应的业务逻辑switch event {case .onRoomEnded(let roomInfo):print("当前所在房间已结束")// ... 处理其他 RoomEvent 事件 ...default: break}}.store(in: &cancellableSet) // 3. 存储订阅关系}}
运行效果 | ![]() |
Store/Component | 功能描述 | API 文档 |
RoomStore | 房间全生命周期管理:创建并加入 / 加入 / 离开 / 结束房间 / 更新、获取房间信息 / 预定房间 / 呼叫房间外成员 / 监听房间内被动事件(如房间解散,房间信息更新等)。 | |
RoomParticipantStore | 房间内参与者管理:设置管理员 / 转移房主 / 获取参与者列表 / 移出房间 / 参与者设备控制(邀请打开摄像头、 麦克风等)/ 申请打开设备(例如申请打开摄像头、麦克风等)。 | |
RoomParticipantView | 单个参与者视频画面展示视图: 绑定和更新参与者信息 / 更新视频流类型 / 设置活跃状态等。 |
RoomParticipantView 在屏幕中是可见状态,并正确调用 RoomParticipantView 的 setActive:true。RoomParticipantView 中设置的 RoomParticipant 的 cameraStatus 状态是否为 on。rsync(xxxx):1:1: SnapKit.framework/SnapKit_Privacy.bundle/: mkpathat: Operation not permitted
rsync 脚本对 SnapKit.framework 资源文件的写入权限,导致框架内的 SnapKit_Privacy.bundle 无法正常拷贝。User Script Sandboxing(或标识 ENABLE_USER_SCRIPT_SANDBOXING),将其值从 YES 修改为 NO。文档反馈