iOS 快速开始与功能指南
iOS:前置条件、安装、Token、加入频道、发布订阅、事件、错误处理与排障;接口名与签名在构建时取自公开 SDK 接口定义。
iOS 端是 Objective-C 选择器形状的原生引擎:AgoraRtcEngineKit 单例 + AgoraRtcEngineDelegate 回调。方法名与声网 iOS SDK 兼容版本逐符号一致(公开 SDK 接口定义,apiVersion 见本页「平台与公开接口定义」)。
前置条件
- Xcode 16+、iOS 15+ 部署目标、Swift 5.9+(也支持 Objective-C)。
Info.plist必须有NSCameraUsageDescription与NSMicrophoneUsageDescription,否则采集会被系统直接拒绝(无弹窗)。- 屏幕共享需要单独的 Broadcast Upload Extension(ReplayKit),并配置 App Group。
- 已拿到
appId与 Token 服务(见 控制台开通服务与获取凭证)。
安装
# Podfile(坐标以发布版本为准)
pod 'NimeetRtc', :path => '../sdk/ios'Swift Package 与 Carthage 形态在发布说明里会同步给出。
获取 Token
客户端不能持有 customerSecret。推荐宿主 App 自带后端签发,Token 通过 RtcTokenProvider 的 callback 形态注入(与 Android 端同一个概念):
let provider = FallbackTokenProvider(providers: [
CallbackTokenProvider { channel, uid, role, completion in
authClient.fetchRtcToken(channel: channel, uid: uid, role: role, completion: completion)
},
StaticTokenProvider(token: ProcessInfo.processInfo.environment["NIMEET_TEST_TOKEN"] ?? "")
])加入频道
import NimeetRtc
final class MeetingController: NSObject, AgoraRtcEngineDelegate {
private var engine: AgoraRtcEngineKit?
func start(appId: String, token: String, localView: UIView) {
let config = AgoraRtcEngineConfig()
config.appId = appId
engine = AgoraRtcEngineKit.sharedEngine(withAppId: appId, delegate: self)
engine?.setChannelProfile(.liveBroadcasting)
engine?.enableVideo()
let canvas = AgoraRtcVideoCanvas()
canvas.view = localView
engine?.setupLocalVideo(canvas)
engine?.startPreview()
let options = AgoraRtcChannelMediaOptions()
options.clientRoleType = .broadcaster
engine?.joinChannel(byToken: token,
channelId: "weekly-sync",
uid: 10001,
mediaOptions: options,
joinSuccess: { channel, uid, elapsed in
print("joined \(channel) uid=\(uid) elapsed=\(elapsed)")
})
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
// 远端用户加入:分配远端画面容器
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) {
// 远端用户离开
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) {
// 错误号分流,见错误处理一节
}
}发布与订阅
原生端没有 publish(track):入会时由 AgoraRtcChannelMediaOptions 决定发布什么,之后用开关方法控制。
engine?.muteLocalAudioStream(true) // 静音麦克风
engine?.muteLocalVideoStream(true) // 关闭摄像头画面
engine?.updateChannelMediaOptions(options) // 切角色 / 改订阅范围屏幕共享用 ReplayKit:宿主 App 启动 Broadcast Upload Extension,扩展里调用 startScreenCapture: 把样本缓冲喂给 SDK。
事件
| 回调 | 何时触发 | 典型处理 |
|---|---|---|
rtcEngine:didJoinedOfUid:elapsed: | 远端用户加入 | 分配容器 |
rtcEngine:firstRemoteVideoDecodedOfUid:size:elapsed: | 远端首帧解码 | 渲染 |
rtcEngine:didOfflineOfUid:reason: | 远端离开 | 释放容器 |
rtcEngine:didOccurError: | 运行时错误 | 按 AgoraErrorCode 分流 |
| Token 将过期回调 | 权限到期前 | 续期后 renewToken: |
错误处理
- 同步方法返回
Int32:0成功,负值为声网错误号。 - 异步错误走
didOccurError。 - 未实现的能力返回
-4(ERR_NOT_SUPPORTED),显式失败。
排障
| 现象 | 原因 | 处理 |
|---|---|---|
| 打开摄像头无反应 | Info.plist 缺 usage description | 补 NSCameraUsageDescription / NSMicrophoneUsageDescription |
| 真机黑屏、模拟器正常 | 模拟器没有摄像头 | 用真机验证采集链路 |
| 入会失败 | Token 与 appId/频道不匹配 | GET /v1/tokens/verify 自查 |
| 屏幕共享无画面 | Extension 未配置 App Group | 检查 extension 的 NSExtension 配置与共享容器 |
| 后台断流 | iOS 挂起应用 | 使用 ReplayKit 或前台音频会话保活策略 |
下一步
平台信息
| 项 | 值 |
|---|---|
| 平台 | iOS |
| 语言 | Swift / Objective-C |
| SDK 包 | NimeetRtc |
| 接口版本 | 4.7.0 |
| 兼容参考 | 声网 ios 端 API |
本端公开接口与声网 ios 端 API 对齐;安装与运行要求见上面前置条件。
可用性
该端 SDK:正式可用。本页代码片段使用公开 API;运行时的能力边界以实际发布的 SDK 包为准。
加入频道链路
下列方法名、参数类型与返回值与同端 API 参考一致。一个平台若有多个重载,这里展示最常用的那一个;完整重载见同端 API 参考页。
| 步骤 | 接口 | 方法 | 重载数 |
|---|---|---|---|
| 开启视频与本地预览 | AgoraRtcEngineKit | enableVideo | 1 |
| 加入频道 | AgoraRtcEngineKit | joinChannelByToken:channelId:info:uid:joinSuccess: | 1 |
| 离开频道 | AgoraRtcEngineKit | leaveChannel: | 1 |
| 创建实例 / 初始化 | AgoraRtcEngineKit | sharedEngineWithAppId:delegate: | 1 |
enableVideo(): int
joinChannelByToken:channelId:info:uid:joinSuccess:(token?: NSString*, channelId: NSString*, info?: NSString*, uid: NSUInteger, joinSuccessBlock?: void(^ )(NSString*channel,NSUInteger uid,NSInteger elapsed)): int
leaveChannel:(leaveChannelBlock?: void(^ )(AgoraChannelStats*stat)): int
sharedEngineWithAppId:delegate:(appId: NSString*, delegate?: id): instancetype事件与回调
该端 SDK 没有事件回调。
错误码
| 常量 | 值 |
|---|---|
AgoraErrorCodeAdmGeneralError | 1005 |
AgoraErrorCodeAdmInitLoopback | 1022 |
AgoraErrorCodeAdmInitPlayout | 1008 |
AgoraErrorCodeAdmInitRecording | 1011 |
AgoraErrorCodeAdmJavaResource | 1006 |
AgoraErrorCodeAdmNoPlayoutDevice | 1360 |
AgoraErrorCodeAdmNoRecordingDevice | 1359 |
AgoraErrorCodeAdmPlayAbnormalFrequency | 1020 |
AgoraErrorCodeAdmRecordAbnormalFrequency | 1021 |
AgoraErrorCodeAdmRecordAudioFailed | 1018 |
AgoraErrorCodeAdmRuntimePlayoutError | 1015 |
AgoraErrorCodeAdmRuntimeRecordingError | 1017 |
AgoraErrorCodeAdmSampleRate | 1007 |
AgoraErrorCodeAdmStartLoopback | 1023 |
AgoraErrorCodeAdmStartPlayout | 1009 |
AgoraErrorCodeAdmStartRecording | 1012 |
AgoraErrorCodeAdmStopPlayout | 1010 |
AgoraErrorCodeAdmStopRecording | 1013 |
AgoraErrorCodeAlreadyInUse | 19 |
AgoraErrorCodeBitrateLimit | 115 |
AgoraErrorCodeBufferTooSmall | 6 |
AgoraErrorCodeConnectionInterrupted | 111 |
AgoraErrorCodeConnectionLost | 112 |
AgoraErrorCodeDecryptionFailed | 120 |
AgoraErrorCodeEncryptedStreamNotAllowedPublish | 130 |
AgoraErrorCodeFailed | 1 |
AgoraErrorCodeInitNetEngine | 21 |
AgoraErrorCodeInvalidAppId | 101 |
AgoraErrorCodeInvalidArgument | 2 |
AgoraErrorCodeInvalidChannelId | 102 |
AgoraErrorCodeInvalidState | 8 |
AgoraErrorCodeInvalidToken | 110 |
AgoraErrorCodeInvalidUserAccount | 134 |
AgoraErrorCodeJoinChannelRejected | 17 |
AgoraErrorCodeLeaveChannelRejected | 18 |
AgoraErrorCodeLoadMediaEngine | 1001 |
AgoraErrorCodeNoError | 0 |
AgoraErrorCodeNoServerResources | 103 |
AgoraErrorCodeNotInChannel | 113 |
AgoraErrorCodeNotInitialized | 7 |
AgoraErrorCodeNotReady | 3 |
AgoraErrorCodeNotSupported | 4 |
AgoraErrorCodePcmSendBufferOverflow | 201 |
AgoraErrorCodePcmSendFormat | 200 |
AgoraErrorCodeResourceLimited | 22 |
AgoraErrorCodeSizeTooLarge | 114 |
AgoraErrorCodeStartCall | 1002 |
AgoraErrorCodeStartCamera | 1003 |
AgoraErrorCodeStartVideoRender | 1004 |
AgoraErrorCodeTimedOut | 10 |
AgoraErrorCodeTokenExpired | 109 |
AgoraErrorCodeTooManyDataStreams | 116 |
AgoraErrorCodeVcmEncoderEncodeError | 1602 |
AgoraErrorCodeVcmEncoderInitError | 1601 |
AgoraErrorCodeVcmEncoderSetError | 1603 |
AgoraErrorCodeVcmUnknownError | 1600 |
AgoraErrorCodeVdmCameraNotAuthorized | 1501 |
AgoraErrorCodeVideoEffectAssetInvalid | 1700 |
AgoraErrorCodeVideoEffectEngineInvalid | 1702 |
AgoraErrorCodeVideoEffectInvalidBundlePath | 1707 |
AgoraErrorCodeVideoEffectInvalidParam | 1705 |
AgoraErrorCodeVideoEffectNodeNotActive | 1704 |
AgoraErrorCodeVideoEffectNotSupported | 1706 |
AgoraErrorCodeVideoEffectSaveFailed | 1701 |
AgoraErrorCodeWatermarkAGRB | 128 |
AgoraErrorCodeWatermarkInfo | 127 |
AgoraErrorCodeWatermarkParam | 124 |
AgoraErrorCodeWatermarkPath | 125 |
AgoraErrorCodeWatermarkPng | 126 |
AgoraErrorCodeWatermarkRead | 129 |
平台 REST 层用 REST 错误码;SDK 层把连接/鉴权失败映射成声网错误号,映射表见 各端 SDK 错误标识。