TUILiveKit 的直播列表能力基于 LiveListView,以竖向分页信息流的形式展示多个直播间,观众上下滑动即可切换,可快速集成到您的应用中。
功能概览
直播间信息流:以竖向分页容器展示多个直播间,每一页都是完整的观看界面。
上下滑动切换:观众上下滑动即可切换到上一个 / 下一个直播间,播放与进房状态由组件自动管理。
首屏置顶:构造时传入的 liveID 会被置顶到列表第一位,保证从分享链接、推送通知进入时首屏看到的就是目标直播间。
分页加载:滑动到列表末尾前自动回调
onLoadMore,可对接 LiveListStore 或您自己的业务服务端追加下一页数据。直播间切换 | 直播观看 |
![]() |
![]() |
组件说明
LiveListView 继承自 UIView,是一个竖向分页的直播间信息流容器,内部基于 UICollectionView 竖向分页实现;每一页内部都由 PlayerView 承载,因此单个直播间的播放能力(拉流、进房、连麦、弹幕、礼物、点赞)与 观众观看 文档完全一致。说明:
宿主 App 必须声明 audio 后台模式(
UIBackgroundModes → audio,即 Target → Signing & Capabilities → Background Modes → Audio, AirPlay, and Picture in Picture)。未声明时 App 进入后台会被系统挂起,观众端将听不到直播间声音。快速接入
步骤1:服务
步骤2:代码集成
注意:
创建 LiveListView 之前,请确保已完成登录,否则拉流与进房会失败。
步骤3:接入 LiveListView 滑动切换直播间
在您的直播列表观看页 Activity 中创建 LiveListView,并为其注入直播间列表数据:
import AtomicXCoreimport SnapKitimport TUILiveKitimport UIKitclass AudienceLiveListViewController: UIViewController {private let liveListView: LiveListViewprivate let pageSize = 6private var isLoading = falseinit(liveID: String = "") {// 1. 创建 LiveListView,传入的 liveID 会作为首屏直播间liveListView = LiveListView(liveID: liveID)super.init(nibName: nil, bundle: nil)}@available(*, unavailable)required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}override func loadView() {// 2. 将 LiveListView 作为控制器的根视图view = liveListView}override func viewDidLoad() {super.viewDidLoad()// 3. 设置加载更多回调,观众滑动到列表末尾前会触发liveListView.onLoadMore = { [weak self] inself?.loadMore()}// 4. 拉取首屏直播间列表并设置给 LiveListViewrefresh()}private func refresh() {guard !isLoading else { return }fetch(cursor: "") { [weak self] inself?.liveListView.setData(LiveListStore.shared.state.value.liveList)}}private func loadMore() {guard !isLoading else { return }let cursor = LiveListStore.shared.state.value.liveListCursorguard !cursor.isEmpty else { return }let oldCount = LiveListStore.shared.state.value.liveList.countfetch(cursor: cursor) { [weak self] inlet list = LiveListStore.shared.state.value.liveListguard list.count > oldCount else { return }self?.liveListView.appendData(Array(list[oldCount..<list.count]))}}private func fetch(cursor: String, completion: @escaping () -> Void) {isLoading = trueLiveListStore.shared.fetchLiveList(cursor: cursor, count: pageSize) { [weak self] result inDispatchQueue.main.async {self?.isLoading = falseswitch result {case .success:completion()case .failure(let error):print("fetchLiveList failed:\\(error.localizedDescription)")}}}}}
说明:
LiveListView 只负责渲染,不负责拉取数据。直播间列表可以来自 AtomicXCore 的 LiveListStore,也可以来自您自己的业务服务端,最终通过
setData / appendData 注入即可。构造时传入的 liveID 会被自动置顶到列表第一位,保证观众首屏看到的就是目标直播间。
观众滑动到距离列表末尾还剩 2 个直播间时,
onLoadMore 会被回调,请在此时追加下一页数据。LiveListView 从窗口移除时会自动停止播放并退出直播间,无需您手动调用
stopPlay / leaveChannel。观众处于连麦中时,组件会自动禁用滑动切换,避免误触导致连麦中断。
步骤4:导航路由到直播列表页面
在您需要跳转到直播列表观看页时,可参考如下代码示例:
// 跳转到「滑动切换直播间」观看页let liveListVC = AudienceLiveListViewController(liveID: "您的直播房间 id")liveListVC.modalPresentationStyle = .fullScreenpresent(liveListVC, animated: false)
组件 API 说明
LiveListView
LiveListView 继承自 UIView,是一个竖向分页的直播间信息流容器。方法 / 属性 | 说明 |
init(liveID: String = "") | 构造方法。liveID 会作为首屏直播间(置顶到列表第一位);不传则展示列表第一条。 |
setData(_ list: [LiveInfo]) | 设置直播间列表数据。内部会自动按 liveID 去重,并将构造传入的 liveID 置顶。 |
appendData(_ list: [LiveInfo]) | 在列表尾部追加直播间数据,用于分页加载。已存在的直播间会被更新而非重复插入。 |
onLoadMore | 闭包回调,观众滑动到距离列表末尾还剩 2 个直播间时触发,用于加载下一页数据。 |
直播间列表数据
组件自身不负责拉列表。列表来自
AtomicXCore 的 LiveListStore:能力 | 接口 |
拉取列表 | LiveListStore.shared.fetchLiveList(cursor:count:completion:) |
列表数据 | LiveListStore.shared.state.value.liveList |
分页游标 | LiveListStore.shared.state.value.liveListCursor(为空表示没有更多数据) |
下一步
恭喜您,现在您已经成功集成了观众观看。接下来,您可以实现主播开播、观众观看等功能,可参考下表:
常见问题
App 退到后台后直播间没有声音?
请检查宿主 App 是否已声明 audio 后台模式:
Target → Signing & Capabilities → Background Modes → 勾选 Audio, AirPlay, and Picture in Picture。未声明时 iOS 会在 App 进入后台后挂起音频会话。调用了 setData 后列表仍然为空?
请先确认:
已调用 setData() 注入数据,且列表中的 liveID 不为空;
已完成 AtomicXCore 登录,
fetchLiveList 回调为 .success;列表数据来自您自己的业务服务端时,已转换为 LiveInfo 对象。
LiveListView 本身不会拉取列表。观众连麦时还能上下滑动切换直播间吗?
不能。观众进入 CO_GUEST 状态后组件会自动禁用滑动切换,避免误触导致连麦中断;连麦结束后恢复。

