AtomicXCore, enabling developers to quickly build multi-party audio/video conference rooms. The SDK follows a pure API architecture, giving you full control over UI customization while letting you focus on business logic and user experience.
RoomStore: Centralized room management, including scheduling, creating, joining rooms, and in-room calling.RoomParticipantStore: Participant management within a room, covering admin settings, host transfer, removing participants, device control, and more.RoomParticipantView: Video view for displaying participant streams within the room.sudo gem install cocoapods in your terminal.sudo gem install cocoapods, you may be prompted for your computer password. Enter your administrator password as instructed.pod 'AtomicXCore' dependency to your project's Podfile:target 'YourProjectTarget' do# Other existing Pod dependencies...# Add pod 'AtomicXCore' dependencypod 'AtomicXCore'end
.xcodeproj directory using cd in the terminal, then run pod init to create a Podfile. Afterward, add the pod 'AtomicXCore' dependency:# If your project directory is /Users/yourusername/Projects/YourProject# 1. cd to your .xcodeproj project directorycd /Users/yourusername/Projects/YourProject# 2. Run pod init. After execution, a Podfile will be generated in your project directory.pod init# 3. Add pod 'AtomicXCore' dependency to the generated Podfiletarget 'YourProjectTarget' do# Add pod 'AtomicXCore' dependencypod 'AtomicXCore'end
cd to the directory containing your Podfile, then run:pod install
Info.plist file.<key>NSCameraUsageDescription</key><string>TUIRoomKit needs access to your camera</string><key>NSMicrophoneUsageDescription</key><string>TUIRoomKit needs access to your microphone</string>

LoginStore.shared.login in your project to complete login. This step is required before using any feature of AtomicXCore.LoginStore.shared.login only after your own user account login is successful. This ensures clarity and consistency in your login flow.import AtomicXCorefunc login() {LoginStore.shared.login(sdkAppID: 1400000001, // Replace with your project's sdkAppIDuserID: "test_001", // Replace with your project's userIDuserSig: "xxxxxxxxxxx") { result in // Replace with your project's userSigswitch result {case .success(let info):debugPrint("login success")case .failure(let error):debugPrint("login failed code:\\(error.code), message:\\(error.message)")}}}
Parameter | Type | Description |
sdkAppID | Int32 | |
userID | String | Unique user identifier. Use only English letters, numbers, hyphens, and underscores. Avoid using simple IDs like 1 or 123 to prevent multi-device login conflicts. |
userSig | String | Authentication ticket for Tencent Cloud. For development: Use GenerateTestUserSig.genTestSig or the UserSig Assistant Tool for a temporary UserSig.For production: Always generate UserSig server-side to prevent secret key leaks. See Calculating UserSig on the Server. |

CreateRoomOptions to set the room name and password.createAndJoinRoom API from RoomStore to execute the operation.import UIKitimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass RoomMainViewController: UIViewController {// Initialize the view controller and automatically create and join the roompublic 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")}// Call this method to create and join the roomprivate func createAndJoinRoom(roomID: String, roomType: RoomType) {// 1. Configure room initialization parameters// CreateRoomOptions defines the basic attributes and initial permission controls of the roomvar options = CreateRoomOptions()options.roomName = "My Discussion" // Set the room display nameoptions.password = "" // Set the room entry password (leave blank if not required)// 2. Set room permissions: control all-member permissions at creation (typically for formal meetings)options.isAllCameraDisabled = false // Enable/disable cameras for all membersoptions.isAllMessageDisabled = false // Enable/disable chat for all membersoptions.isAllMicrophoneDisabled = false // Enable/disable microphones for all membersoptions.isAllScreenShareDisabled = false // Enable/disable screen sharing for all members// 3. Create and join room// If the room does not exist, it will be created first, then joined automaticallyRoomStore.shared.createAndJoinRoom(roomID: roomID, roomType: roomType, options: options) { [weak self] result inguard let self = self else { return }switch result {case .success():print("Room created and joined successfully")case .failure(let error):print("Failed to create and join room [Error code: \\(error.code)]: \\(error.message)")}}}}
Parameter Name | Type | Required | Description |
roomID | String | Yes | Unique room identifier (string). Limit: 0-48 bytes. Use only numbers, English letters (case-sensitive), underscores (_), and hyphens (-). Avoid spaces and Chinese characters. |
roomType | RoomType | Yes | Room type: standard: Standard room, all members can freely interact via audio/video. webinar: Large seminar room, distinguishes between guest and audience roles; audience cannot go on stage by default. |
options | CreateRoomOptions | Yes | Room creation configuration object. For usage details, see CreateRoomOptions struct documentation. |
completion | CompletionClosure | No | Completion callback. Returns the result of creating and joining the room. If creation fails, returns error code and message. |
Parameter Name | Type | Required | Description |
roomName | String | No | Room name (optional, defaults to empty string). Limit: 0-60 bytes. Supports English, Chinese, numbers, special characters. |
password | String | No | Room password. Empty string "" means no password. Limit: 0-32 bytes. Recommend using 4-8 digits for easy mobile input. If set, other users must enter the password to join. Avoid storing plaintext sensitive information. |
isAllMicrophoneDisabled | Bool | No | Disable microphones for all members. When enabled, only host/admin can unmute; regular participants are muted by default. true: Disabled. false: Not disabled (default). |
isAllCameraDisabled | Bool | No | Disable cameras for all members. When enabled, only host/admin can enable cameras; regular participants are disabled by default. true: Disabled. false: Not disabled (default). |
isAllScreenShareDisabled | Bool | No | Disable screen sharing for all members. When enabled, only host/admin can share screen. true: Disabled. false: Not disabled (default). |
isAllMessageDisabled | Bool | No | Disable chat messages for all members (mute). When enabled, regular participants cannot send text messages in the room. true: Disabled. false: Not disabled (default). |
openLocalCamera and openLocalMicrophone APIs from the DeviceStore singleton to enable local devices.import UIKitimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass 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")}// Enable devicesprivate func openDevices() {// 1. Enable front cameraDeviceStore.shared.openLocalCamera(isFront: true, completion: nil)// 2. Enable microphoneDeviceStore.shared.openLocalMicrophone(completion: nil)}}
Parameter Name | Type | Required | Description |
isFront | Bool | Yes | Enable the front camera. true: Front camera . false: Rear camera. |
completion | CompletionClosure | No | Completion callback. Returns the result of enabling the camera. If enabling fails, returns error code and message. |
endRoom API from RoomStore. All participants will receive a room ended event.import UIKitimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass 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")}// End the roomprivate func endRoom() {// endRoom API permanently ends the current room.// Note: Typically, only the host (owner) can perform this operation. After execution, all members are removed from the room and audio/video capture is forcibly stopped.RoomStore.shared.endRoom { [weak self] result inguard let self = self else { return }switch result {case .success():print("Room ended successfully")case .failure(let error):print("Failed to end room [Error code: \\(error.code)]: \\(error.message)")}}}}

joinRoom API from RoomStore. Other participants will receive a participant joined event notification.import UIKitimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass 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")}// Join an existing roomprivate func joinRoom(roomID: String, roomType: RoomType) {// 1. Prepare join parameters// joinRoom is used for joining a known and ongoing roomlet targetRoomID = roomID // Target room IDlet roomPassword = "" // Room password, pass empty string or nil if not set// 2. Call RoomStore joinRoom API// This operation verifies if the room exists, if the user is banned, and if the password is correctRoomStore.shared.joinRoom(roomID: targetRoomID, roomType: roomType, password: roomPassword) { [weak self] result inguard let self = self else { return }switch result {case .success():print("Joined room successfully")case .failure(let error):print("Failed to join room [Error code: \\(error.code)]: \\(error.message)")}}}}
Parameter Name | Type | Required | Description |
roomID | String | Yes | Unique room identifier (string). Limit: 0-48 bytes. Use only numbers, English letters (case-sensitive), underscores (_), and hyphens (-). Avoid spaces and Chinese characters. |
roomType | RoomType | Yes | Room type: standard: Standard room, all members can freely interact via audio/video. webinar: Large seminar room, distinguishes between guest and audience roles; audience cannot go on stage by default. |
password | String | Yes | Room password. Empty string "" means no password. Limit: 0-32 bytes. Recommend using 4-8 digits for easy mobile input. If set, other users must enter the password to join. Avoid storing plaintext sensitive information. |
completion | CompletionClosure | No | Completion callback. Returns the result of joining the room. If joining fails, returns error code and message. |
leaveRoom API from RoomStore. Other participants will receive a participant left event notification.import UIKitimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass 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")}// Leave the current roomprivate func leaveRoom() {// 1. Business logic// leaveRoom API is used for regular members or host to leave the room.// Unlike endRoom, when the host calls leaveRoom, only they leave; the room remains.// 2. Call RoomStore leaveRoom API// This operation stops audio/video streaming and notifies the server to remove the current user from the roomRoomStore.shared.leaveRoom { [weak self] result inguard let self = self else { return }switch result {case .success():print("Left room successfully")case .failure(let error):print("Failed to leave room [Error code: \\(error.code)]: \\(error.message)")}}}}
RoomParticipantView component in AtomicXCore SDK provides a complete solution for video rendering. It supports real-time display of both local camera feeds and remote participant streams, and is easy to integrate.
RoomParticipantView is the core view component for rendering participant video streams in the room. For more flexible video layout options, see TUIRoomKit open source project, specifically RoomView.swift.RoomParticipantStore.state.participantList for participant state changes.participantList state.RoomParticipantView instances based on participant data and bind video rendering logic.import UIKitimport Combineimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass RoomMainViewController: UIViewController {private var participantStore: RoomParticipantStoreprivate var cancellableSet = Set<AnyCancellable>()private var views = [RoomParticipantView]()init(roomID: String) {// RoomParticipantStore is bound to the room and must be created via RoomParticipantStore.create(roomID: String) factory method for a specific roomparticipantStore = RoomParticipantStore.create(roomID: roomID)super.init(nibName: nil, bundle: nil)// 1. Subscribe to Data LayersubscribeParticipantState()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. Automatic State SyncupdateParticipantView(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. Initialize Viewlet 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. Integrate UIview.addSubview(participantView)participantView.setActive(isActive: true)return participantView}}}
Parameter Name | Type | Required | Description |
streamType | VideoStreamType | Yes | Type of video stream to render. camera: Camera stream.screen: Screen sharing stream. |
participant | RoomParticipant | Yes | Real-time participant object in the room, including identity, business state, and audio/video device permissions. |
Parameter Name | Type | Required | Description |
userID | String | Yes | Unique identifier for the user. |
userName | String | No | User nickname. |
avatarURL | String | No | URL address of the user's avatar. |
nameCard | String | No | User's name card or remark in the room. Limit: 0-32 bytes. Supports English, Chinese, numbers, special characters. |
role | ParticipantRole | No | Participant role in the room. owner: Host. admin: Admin. generalUser: Regular user (default). |
roomStatus | RoomParticipantStatus | No | Participant status in the room. scheduled: Scheduled (default). inCalling: Calling. callTimeout: Call timeout. callRejected: Call rejected. inRoom: In the room. |
microphoneStatus | DeviceStatus | No | Microphone device status. off: Off (default). on: On. |
cameraStatus | DeviceStatus | No | Camera device status. off: Off (default). on: On. |
screenShareStatus | DeviceStatus | No | Screen sharing status. off: Off (default). on: On. |
isMessageDisabled | Bool | No | Whether the participant is muted. If true, cannot send chat messages. true: Disabled. false: Not disabled (default). |
metaData | [String: String] | No | Business custom extension data, synchronized with participant state. Limit: 0-60 bytes. Supports only JSON string. |
RoomStore's roomEventPublisher for RoomEvent.import UIKitimport Combineimport AtomicXCore// RoomMainViewController represents the main view controller of the roomclass RoomMainViewController: UIViewController {private let roomID: String// Stores Combine subscriptions to prevent listener invalidation due to object destructionprivate var cancellableSet = Set<AnyCancellable>()public init(roomID: String) {self.roomID = roomIDsuper.init(nibName: nil, bundle: nil)// Start event listening during initializationsubscribeRoomEvents()}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}// Subscribe to passive room eventsprivate func subscribeRoomEvents() {// 1. Access RoomStore's roomEventPublisher// This Publisher pushes events throughout the room lifecycle, such as calling, dissolution, scheduled reminders, etc.RoomStore.shared.roomEventPublisher.receive(on: RunLoop.main) // Ensure UI logic is handled on the main thread.sink { [weak self] event inguard let self = self else { return }// 2. Execute business logic based on event typeswitch event {case .onRoomEnded(let roomInfo):print("The current room has ended")// ... Handle other RoomEvent events ...default: break}}.store(in: &cancellableSet) // 3. Store subscription relationship}}
Demo Effect | ![]() |
Multi-Party Room Feature | Feature Introduction | Implementation Guide |
Update Room Information | The host can update parts of the room information, such as room name and password. | |
In-Meeting Calling | The host or admin can call users who have not entered the room to join. | |
Room Scheduling | Rooms can be scheduled in advance, supporting start time, end time, and adding participants. | |
Member Management | The host can manage other participants in the room, such as setting admins, removing participants, and controlling individual participant audio/video status. |
Store/Component | Feature Description | API Documentation |
RoomStore | Complete room lifecycle management: create and join / join / leave / end room / update and get room info / schedule room / call external members / listen to passive room events (such as room dissolution, room info update, etc.). | |
RoomParticipantStore | Participant management within the room: set admin / transfer host / get participant list / remove from room / participant device control (invite to enable camera, microphone, etc.) / request to enable device (e.g., request to enable camera, microphone, etc.). | |
RoomParticipantView | Single participant video display view: bind and update participant info / update video stream type / set active state, etc. |
RoomParticipantView is visible on screen and that RoomParticipantView's setActive: true is called correctly.cameraStatus of the RoomParticipant set in RoomParticipantView is on.rsync(xxxx):1:1: SnapKit.framework/SnapKit_Privacy.bundle/: mkpathat: Operation not permitted
rsync script's write permissions to the SnapKit.framework resource files during the build process, causing the SnapKit_Privacy.bundle in the framework to fail to copy.User Script Sandboxing (or ENABLE_USER_SCRIPT_SANDBOXING), and change its value from YES to NO.피드백