View component purpose-built for live streaming scenarios. It serves as the foundation of your live streaming implementation, encapsulating all complex streaming technologies—including stream publishing and playback, co-hosting, and audio/video rendering. Use LiveCoreView as the "canvas" for your live video, enabling you to focus on developing your custom UI and interactions.
Core Concept | Core Responsibility | Key API / Property |
LiveCoreView | Handles publishing, playing, and rendering audio/video streams. Provides adapter interfaces for integrating custom UI components (e.g., user info, PK progress bar). | viewType:.pushView (host publishing view).playView (audience playback view)setLiveId(): Binds the live room ID for this view.videoViewDelegate: Adapter for custom video display UI slots. |
LiveListStore | Manages the complete live room lifecycle (create, join, leave), synchronizes state, and listens for passive events (e.g., live ended, kicked out). | createLive(): Start live stream as host.endLive(): End live stream as host.joinLive(): Audience joins live room.leaveLive(): Leave live room. |
LiveInfo | Defines room parameters before going live, such as room ID, seat layout mode, max co-hosts, etc. | liveID: Unique room identifier.seatLayoutTemplateID: Layout template ID (e.g., 600 for dynamic grid). |
SDKAppID: Application identifier (required). Tencent Cloud uses SDKAppID for billing and details.SDKSecretKey: Application secret key, used to initialize the configuration file with secret information.
pod 'AtomicXCore' to your Podfile, then run pod install.target 'xxxx' dopod 'AtomicXCore'end
Info.plist file.<key>NSCameraUsageDescription</key><string>TUILiveKit needs camera access to enable video recording with picture</string><key>NSMicrophoneUsageDescription</key><string>TUILiveKit needs microphone permission to enable sound in recorded videos</string>

LoginStore.shared.login in your project to complete authentication. This is required before using any functionality of AtomicXCore.import AtomicXCore// AppDelegate.swiftfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {LoginStore.shared.login(sdkAppID: 1400000001, // Replace with your SDKAppIDuserID: "test_001", // Replace with your UserIDuserSig: "xxxxxxxxxxx") { result in // Replace with your UserSigswitch result {case .success(let info):debugPrint("login success")case .failure(let error):debugPrint("login failed code:\\(error.code), message:\\(error.message)")}}return true}
Parameter | Type | Description |
SDKAppID | Int | |
UserID | String | The unique ID for the current user. Must contain only English letters, numbers, hyphens, and underscores. |
userSig | String | A ticket for Tencent Cloud authentication. Please note: Development Environment: You can use the local GenerateTestUserSig.genTestSig function to generate a UserSig or generate a temporary UserSig via the UserSig Generation Tool.Production Environment: To prevent key leakage, you must use a server-side method to generate UserSig. For details, see Generating UserSig on the Server. |

LiveCoreView instance and set viewType to .pushView.import AtomicXCore// YourAnchorViewController represents your broadcaster streaming view controllerclass YourAnchorViewController: UIViewController {private let liveId: String// 1. Add LiveCoreView as a property of your view controllerprivate let coreView = LiveCoreView(viewType: .pushView, frame: UIScreen.main.bounds)// 2. Add a convenience initializer for instance initialization// - liveId: The ID of the live room to start streamingpublic init(liveId: String) {self.liveId = liveIdsuper.init(nibName: nil, bundle: nil)self.coreView.setLiveID(liveId)}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}public override func viewDidLoad() {super.viewDidLoad()// 3. Add the broadcaster streaming view to your viewview.addSubview(coreView)}}
DeviceStore.shared.openLocalCamera and DeviceStore.shared.openLocalMicrophone to open the camera and microphone. No further action is required—LiveCoreView automatically previews the current camera video stream.import AtomicXCoreclass YourAnchorViewController: UIViewController {// ... other code ...public override func viewDidLoad() {super.viewDidLoad()// Enable devicesopenDevices()}private func openDevices() {// 1. Enable front cameraDeviceStore.shared.openLocalCamera(isFront: true, completion: nil)// 2. Enable microphoneDeviceStore.shared.openLocalMicrophone(completion: nil)}}
LiveListStore.shared.createLive to start streaming.import AtomicXCoreclass YourAnchorViewController: UIViewController {// ... other code ...// Call the start streaming interface to begin live streamingprivate func startLive() {var liveInfo = LiveInfo()// 1. Set the live room IDliveInfo.liveID = self.liveId// 2. Set the live room nameliveInfo.liveName = "test live"// 3. Configure layout template, default: 600 dynamic grid layoutliveInfo.seatLayoutTemplateID = 600// 4. Keep the broadcaster always on the seatliveInfo.keepOwnerOnSeat = true// 5. Call LiveListStore.shared.createLive to start streamingLiveListStore.shared.createLive(liveInfo) { [weak self] result inguard let self = self else { return }switch result {case .success(let info):debugPrint("startLive success")case .failure(let error):debugPrint("startLive error:\\(error.message)")}}}}
LiveInfo Parameter Descriptions:Parameter Name | Type | Attribute | Description |
liveID | String | Required | Unique identifier for the live room. |
liveName | String | Optional | Title of the live room. |
notice | String | Optional | Announcement for the live room. |
isMessageDisable | Bool | Optional | Whether to mute chat (true: yes, false: no). |
isPublicVisible | Bool | Optional | Whether the room is publicly visible (true: yes, false: no). |
isSeatEnabled | Bool | Optional | Whether to enable seat functionality (true: yes, false: no). |
keepOwnerOnSeat | Bool | Optional | Whether to keep the owner on the seat. |
maxSeatCount | Int | Required | Maximum number of seats. |
seatMode | TakeSeatMode | Optional | Seat mode (.free: free to take seat, .apply: apply to take seat). |
seatLayoutTemplateID | UInt | Required | Seat layout template ID. |
coverURL | String | Optional | Cover image URL for the live room. |
backgroundURL | String | Optional | Background image URL for the live room. |
categoryList | NSNumber | Optional | Category tag list for the live room. |
activityStatus | Int | Optional | Live activity status. |
isGiftEnabled | Bool | Optional | Whether to enable gift functionality (true: yes, false: no). |
LiveListStore.shared.endLive to stop streaming and destroy the room. The SDK handles cleanup automatically.import AtomicXCoreclass YourAnchorViewController: UIViewController {// ... other code ...// End live streamingprivate func stopLive() {LiveListStore.shared.endLive { [weak self] result inguard let self = self else { return }switch result {case .success(let data):debugPrint("endLive success")case .failure(let error):debugPrint("endLive error: \\(error.message)")}}}}

LiveCoreView instance and set viewType to .playView.import AtomicXCoreclass YourAudienceViewController: UIViewController {// 1. Initialize the audience playback pageprivate let coreView = LiveCoreView(viewType: .playView, frame: UIScreen.main.bounds)private let liveId: Stringpublic init(liveId: String) {self.liveId = liveIdsuper.init(nibName: nil, bundle: nil)// 2. Bind the live IDself.coreView.setLiveID(liveId)}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}public override func viewDidLoad() {super.viewDidLoad()// 3. Add the playback view to your viewview.addSubview(coreView)}}
LiveListStore.shared.joinLive to join the live stream. No further action is required—LiveCoreView will automatically play the current room's video stream.import AtomicXCoreclass YourAudienceViewController: UIViewController {// ... other code ...public override func viewDidLoad() {super.viewDidLoad()view.addSubview(coreView)// 4. Join the live roomjoinLive()}private func joinLive() {// Call LiveListStore.shared.joinLive to enter the live room// - liveId: Same liveId as the broadcasterLiveListStore.shared.joinLive(liveID: liveId) { [weak self] result inguard let self = self else { return }switch result {case .success(let info):debugPrint("joinLive success")case .failure(let error):debugPrint("joinLive error \\(error.message)")// If joining fails, exit the page// self.dismiss(animated: true)}}}}
LiveListStore.shared.leaveLive to exit. The SDK will automatically stop playback and leave the room.import AtomicXCoreclass YourAudienceViewController: UIViewController {// ... other code ...// Leave the live roomprivate func leaveLive() {LiveListStore.shared.leaveLive { [weak self] result inguard let self = self else { return }switch result {case .success:debugPrint("leaveLive success")case .failure(let error):debugPrint("leaveLive error \\(error.message)")}}}}
liveListEventPublisher from LiveListStore to listen for events:import AtomicXCoreimport Combine // 1. Import the Combine frameworkclass YourAudienceViewController: UIViewController {// ... other code (coreView, liveId, init, deinit, joinLive, leaveLive, etc.) ...// 2. Define cancellableSet to manage subscription lifecycleprivate var cancellableSet: Set<AnyCancellable> = []public override func viewDidLoad() {super.viewDidLoad()view.addSubview(coreView)// 3. Listen for live eventssetupLiveEventListener()// 4. Join the live roomjoinLive()}// 5. Add a method to set up event listenersprivate func setupLiveEventListener() {LiveListStore.shared.liveListEventPublisher.receive(on: RunLoop.main) // Ensure UI updates are handled on the main thread.sink { [weak self] event inguard let self = self else { return }switch event {case .onLiveEnded(let liveID, let reason, let message):// Live stream endeddebugPrint("Live ended. liveID: \\(liveID), reason: \\(reason.rawValue), message: \\(message)")// Handle logic to exit the live room, e.g., close the current page// self.dismiss(animated: true)case .onKickedOutOfLive(let liveID, let reason, let message):// Kicked out of live streamdebugPrint("Kicked out of live. liveID: \\(liveID), reason: \\(reason.rawValue), message: \\(message)")// Handle logic to exit the live room// self.dismiss(animated: true)}}.store(in: &cancellableSet) // Manage subscription}// ... joinLive() and leaveLive() methods ...}
LiveCoreView, you will have a pure video rendering view with full live streaming capabilities, but without any interactive UI. To add interactive features, see Enriching the Live Streaming Scene. | Dynamic Grid Layout | Floating Window Layout | Fixed Grid Layout | Fixed Window Layout |
Template ID | 600 | 601 | 800 | 801 |
Description | Default layout; grid size adjusts dynamically based on number of co-hosts. | Co-hosts are displayed as floating windows. | Fixed number of co-hosts; each occupies a fixed grid. | Fixed number of co-hosts; guests are displayed as fixed windows. |
Example | ![]() | ![]() | ![]() | ![]() |
metaData feature of LiveListStore to achieve this.updateLiveMetaData API. AtomicXCore will synchronize these changes in real time to all audience members.LiveListState.currentLive and listen for changes in metaData. When a relevant key is updated, parse its value and update your business state.import AtomicXCoreimport Combine// 1. Define a background music model (recommended: Codable)struct MusicModel: Codable {let musicId: Stringlet musicName: String}// 2. Host side: Push background music infofunc updateBackgroundMusic(music: MusicModel) {guard let jsonData = try? JSONEncoder().encode(music),let jsonString = String(data: jsonData, encoding: .utf8) else { return }let metaData = ["music_info": jsonString]LiveListStore.shared.updateLiveMetaData(metaData) { result inif case .success = result {print("Background music \\(music.musicName) pushed successfully")} else if case .failure(let error) = result {print("Background music push failed: \\(error.message)")}}}// 3. Audience side: Subscribe and update business logicprivate func subscribeToDataUpdates() {LiveListStore.shared.state// Listen for metaData changes in the current room.subscribe(StatePublisherSelector(keyPath: \\LiveListState.currentLive)).map { $0.metaData["music_info"] }.removeDuplicates().receive(on: DispatchQueue.main).sink { jsonString inguard let jsonString = jsonString,let data = jsonString.data(using: .utf8),let music = try? JSONDecoder().decode(MusicModel.self, from: data) else {return}// Update business state, play new music// ... (e.g.: playMusic(music))}.store(in: &cancellables)}
Feature | Description | Store | Implementation Guide |
Enable Audience Audio/Video Co-hosting | Audience can apply to join the host and interact via real-time video. | ||
Enable Host Cross-room PK | Hosts from different rooms can connect for interaction or PK. | ||
Add Bullet Chat Feature | Audience can send and receive real-time text messages in the live room. | ||
Build a Gift Giving System | Audience can send virtual gifts to the host, increasing engagement and fun. |
Store/Component | Description | API Reference |
LiveCoreView | Core view component for displaying and interacting with live video streams. Handles video rendering and view widgets, supports host streaming, audience co-hosting, host connections, and more. | |
LiveListStore | Manages the full lifecycle of live rooms: create/join/leave/destroy rooms, query room list, modify live info (name, announcement, etc.), and listen to live status events (e.g., kicked out, ended). | |
DeviceStore | Controls audio/video devices: microphone (on/off, volume), camera (on/off, switch, quality), screen sharing, and real-time device status monitoring. | |
CoGuestStore | Manages audience co-hosting: apply/invite/accept/reject co-host requests, member permission control (microphone/camera), and status synchronization. | |
CoHostStore | Handles host cross-room connections: supports multiple layout templates (dynamic grid, etc.), initiates/accepts/rejects connections, and manages co-host interactions. | |
BattleStore | Manages host PK battles: initiate PK (set duration/opponent), manage PK status (start/end), synchronize scores, and listen for battle results. | |
GiftStore | Handles gift interactions: get gift list, send/receive gifts, and listen for gift events (including sender and gift details). | |
BarrageStore | Supports live chat: send text/custom danmaku, maintain danmaku list, and monitor danmaku status in real time. | |
LikeStore | Handles like interactions: send likes, listen for like events, and synchronize total like count. | |
LiveAudienceStore | Manages audience: get real-time audience list (ID/name/avatar), count audience, and listen for join/leave events. | |
AudioEffectStore | Audio effects: voice change (child/male), reverb (KTV, etc.), ear return adjustment, and real-time effect switching. | |
BaseBeautyStore | Basic beauty filters: adjust smoothing/whitening/rosiness (0-9), reset beauty status, and synchronize effect parameters. |
setLiveID: Ensure you have set the correct liveID for the LiveCoreView instance before calling start or join methods.DeviceStore.shared().openLocalCamera(true)to enable the camera?LiveCoreView) has its viewType set to PUSH_VIEW.LiveCoreView) has its viewType set to PLAY_VIEW.updateLiveMetaData?updateLiveMetaData. Regular audience members cannot.rsync(xxxx):1:1: SnapKit.framework/SnapKit_Privacy.bundle/: mkpathat: Operation not permitted
SnapKit.framework resource files during the build process, causing the SnapKit_Privacy.bundle in the framework to fail to copy properly.ENABLE_USER_SCRIPT_SANDBOXING), and change its value from YES to NO.Feedback