外观
iOS 接入
需要查某个方法的参数、返回值或回调时,查看 iOS 方法参考。
iOS SDK 提供 PopoIMKit 模块和两个 UIKit 根 Controller,可放入现有 TabBar,也可从业务页面直接打开聊天。SDK 不要求宿主继承专用基类。
环境与本地接入
- 最低 iOS 15.0,面向 Swift 宿主。
- 包使用 Swift 5 语言模式,
Package.swift工具版本为 5.9。 - UI 使用 UIKit;Objective-C 与 CocoaPods 不在当前接入范围。
在 Xcode 选择 File → Add Package Dependencies → Add Local,选中包含 Package.swift 的 ios/ 目录,将 PopoIMKit 产品加入应用 Target。保留源码中的 Sources/PopoIMKit/Resources,其中包含 SDK 资源和隐私清单。
SwiftPM 会根据包清单解析腾讯 TRTC 依赖。宿主只导入一个模块:
swift
import UIKit
import PopoIMKit初始化与 AuthProvider
在应用启动且用户同意隐私政策后执行一次初始化。PopoIM UI 与会话入口在主 Actor 上调用;Provider 通过宿主后端异步获取当前账号凭证。
swift
@MainActor
func configureIM(hostAuth: HostAuthClient) throws {
let config = PopoConfig(
serverURL: "https://example.com",
webSocketURL: "wss://example.com/ws"
) {
try await hostAuth.fetchImAuth()
}
try PopoIM.initialize(config)
}HostAuthClient 是宿主自己的网络适配,fetchImAuth() 返回 PopoAuthInfo。将认证接口结果转换一次:
swift
let auth = PopoAuthInfo(
user: PopoUser(
userID: userID,
username: username,
nickname: nickname,
avatar: avatar,
signature: signature
),
token: token,
expireAt: expireAt // Int64,Unix 秒
)Provider 为 @Sendable () async throws -> PopoAuthInfo,宿主网络实现应满足 Swift 的并发要求;失败直接抛错。webSocketURL 可省略,默认使用服务地址的 /ws。初始化不请求网络,不能用反复初始化的方式切换账号或 Token。
两个 UI 入口
由宿主持有导航栈和底部标签:
swift
@MainActor
func makeMessagingTabs() -> UITabBarController {
let messages = UINavigationController(
rootViewController: PopoConversationController()
)
let contacts = UINavigationController(
rootViewController: PopoContactController()
)
messages.tabBarItem = UITabBarItem(
title: "消息", image: UIImage(systemName: "message"), tag: 0
)
contacts.tabBarItem = UITabBarItem(
title: "通讯录", image: UIImage(systemName: "person.2"), tag: 1
)
let tabs = UITabBarController()
tabs.viewControllers = [messages, contacts]
return tabs
}两个根页可以独立嵌入。宿主的“我的”、登录、资料编辑和推送落地保留在自身导航中;SDK 处理聊天、好友和群等内部页面。
登录、退出与账号切换
swift
// 以下代码在 @MainActor 上执行。
// 可选:verifiedUser 来自宿主已确认的本机账号。
try await PopoIM.restoreCachedSession(user: verifiedUser)
try await PopoIM.login()
// 宿主完成账号切换,Provider 改为返回新用户后:
try await PopoIM.login()
// 用户退出宿主,同时移除该账号的本地数据。
PopoIM.logout(clearLocalData: true)login() 等待认证和首次同步;缓存恢复不请求 Token,也不代表在线就绪。显式登录可以切号,自动续期保持原身份。登录网络失败时可继续显示已有只读缓存,不应伪造登录成功。
UIKit 回调场景也可使用 PopoIM.login { error in ... },error == nil 表示成功,回调在主线程。取消某个 Swift Task 只取消该调用方的等待,退出进程共享会话仍使用 logout()。
常用公开操作
swift
// 使用宿主当前页面的 UINavigationController。
try await PopoIM.openConversation(
try .friend("linzhou"),
from: navigationController
)
try await PopoIM.openConversation(
try .group("6655312956"),
from: navigationController
)
let observer = PopoIM.addUnreadListener { count in
// 替换宿主角标状态,100 显示为 99+。
renderUnread(count.conversation, count.contact)
}
try await PopoIM.updateCurrentUser(updatedUser)
let bytes = await PopoIM.cacheSize()
let remainingBytes = await PopoIM.clearCache()
// 宿主相应生命周期结束时:
PopoIM.removeUnreadListener(observer)renderUnread 是宿主的展示逻辑;闭包捕获 Controller 时使用弱引用。缓存返回单位为字节,清理保留会话、消息、草稿和待发送内容。
打开指定消息可使用 openConversation(target, at: messageID, from: navigationController)。SDK 将页面压入传入的导航栈,不会替宿主切换 Tab;从通知打开时应先选中预期宿主标签。需要本人好友码时可调用 PopoUIKit.createFriendQRCode(username:size:)。
权限、主题与推送
启用相应媒体能力时,在宿主 Info.plist 中配置用途说明:
xml
<key>NSMicrophoneUsageDescription</key>
<string>用于发送语音消息及进行语音和视频通话</string>
<key>NSCameraUsageDescription</key>
<string>用于拍摄图片、视频、扫描二维码及进行视频通话</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>用于将图片和视频保存到相册</string>SDK 在用户发起录音、拍摄、保存或通话时才申请所需权限。系统 PHPicker 选图不要求照片库读取权限。拒绝权限应保留可返回的页面与重新尝试入口,避免在进入首页时统一申请权限。
深浅色跟随宿主窗口的 UIKit trait;宿主通过 overrideUserInterfaceStyle 管理外观。普通推送、通知授权和桌面角标由宿主负责。若接入海外系统通话,还涉及公开的 PushKit / CallKit 接线入口,应结合宿主的签名、后台能力与服务端配置单独验收。
接入检查
在真机验证从两个根页进入聊天、从业务页直接打开会话、交互返回、后台恢复和账号切换。媒体另验证权限拒绝、选择取消、竖屏视频及保存;通话需要两台设备检查前后台与音频路由。
