跳转到正文

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 接线入口,应结合宿主的签名、后台能力与服务端配置单独验收。

接入检查 ​

在真机验证从两个根页进入聊天、从业务页直接打开会话、交互返回、后台恢复和账号切换。媒体另验证权限拒绝、选择取消、竖屏视频及保存;通话需要两台设备检查前后台与音频路由。