# 从 CNB 中克隆代码git clone https://cnb.cool/tencent/cloud/trtc/TUIKit_iOS.git# 从 GitHub 中克隆代码git clone https://github.com/Tencent-RTC/TUIKit_iOS.git
chat、call 文件夹整体复制到您的工程根目录下。复制完成后的目录结构如下:YourApplication/├── source/ # 您的工程代码├── call/ # 音视频通话组件│ └── TUICallKit_Swift.podspec│ └── TUICallKit_Swift/├── chat/ # Chat 源码│ ├── demo/ # 示例工程│ └── uikit/ # TUIChatKit 组件库├── Podfile # 依赖配置文件├── YourApplication.xcworkspace # 您的项目文件
chat/ 目录下(chat/uikit 为 UIKit 组件库,chat/demo 为示例工程),其依赖的音视频通话组件 call/TUICallKit_Swift 位于仓库根目录。模块目录可放在工程任意位置,只需在 Podfile 中设置正确的相对路径即可。# 请使用您的真实项目名称替换 your_project_nametarget 'your_project_name' do# 补充如下内容 增加 TUIChatKit 和 TUICallKit_Swift 这两个依赖# 注意 path 的相对路径pod 'TUIChatKit', :path => 'chat/uikit/TUIChatKit.podspec'pod 'TUICallKit_Swift', :path => 'call/TUICallKit_Swift.podspec'end
pod install# 如果无法安装 TUIKit 最新版本,执行以下命令更新本地的 CocoaPods 仓库列表。# pod repo update# pod update

LoginStore 的 login 接口,传入上文获取的 sdkAppID、userID、userSig 进行登录鉴权:import AtomicXCoreimport TUIChatKitimport UIKitlet yourSdkAppID: Int32 = 10_000_000_00 // 填写你的实际sdkAppIDlet testUserID = "testUserID" // 你的测试用户IDlet userSig = "xxxxxxx" // 你的测试用户ID对应的 userSig (从IM 控制台获取,看上面的截图)LoginStore.shared.login(sdkAppID: yourSdkAppID, userID: testUserID, userSig: userSig) { [weak self] result inDispatchQueue.main.async {switch result {case .success:// 登录成功后 显示会话列表// self?.showConversationList()case .failure(let error):print("login failed: \\(error.code) \\(error.message)")}}}
import AtomicXCoreimport TUIChatKitimport UIKitfunc showConversationList() {let conversationsPage = ConversationsPage(onConversationClick: { [weak self] info in// 点击会话列表中的某条会话后,进入对应的聊天页// self?.showChat(info.conversation)})navigationController.pushViewController(conversationsPage, animated: true)}
ConversationsPage 会自动从本地数据库加载最近会话。当用户点击某条会话时,ConversationsPage 会通过 onConversationClick 回调,把所选会话的信息传递给上层,您可以在该回调中创建并进入聊天页(见 步骤 4)。ConversationInfo,用于指定要进入的会话。其中 conversationID 与 type 是必填的关键字段,title 用于聊天页导航栏标题的初始展示。import AtomicXCoreimport TUIChatKitimport UIKit// 进入单聊let userID = "test_user"var conversation = ConversationInfo(conversationID: ChatUtil.getC2CConversationID(userID))conversation.type = .c2cconversation.title = "与 \\(userID) 聊天"showChat(conversation)// 进入群聊let groupID = "@TGS#xxxxxx"var groupConversation = ConversationInfo(conversationID: ChatUtil.getGroupConversationID(groupID))groupConversation.type = .groupgroupConversation.title = "测试群"showChat(groupConversation)func showChat(_ info: ConversationInfo) {let chatPage = ChatPage(conversation: info, onBack: { [weak self] inself?.navigationController.popViewController(animated: true)})navigationController.pushViewController(chatPage, animated: true)}
<key>NSCameraUsageDescription</key><string>需要访问您的相机权限,开启后才能发送图片或视频</string><key>NSMicrophoneUsageDescription</key><string>需要访问您的麦克风权限,开启后才能发送语音</string><key>NSPhotoLibraryAddUsageDescription</key><string>需要访问您的相册权限,开启后保存图片或视频</string><key>NSPhotoLibraryUsageDescription</key><string>需要访问您的相册权限,开启后才能发送图片或视频</string>
import AtomicXCoreimport TUIChatKitimport UIKitfunc showContacts() {let contactsPage = ContactsPage(onContactClick: { [weak self] contact in// 点击好友列表中的某个联系人回调(ContactInfo),可在该回调中进入单聊// self?.showChat(with: contact.userID, title: contact.nickname ?? contact.userID)},onGroupClick: { [weak self] group in// 点击群列表中的某个群的回调(GroupInfo),可在该回调中进入群聊// self?.showGroupChat(with: group.groupID, title: group.groupName)})navigationController.pushViewController(contactsPage, animated: true)}
LoginStore 登录只建立了消息通道,在登录成功后,通话引擎需单独初始化:import RTCRoomEngineimport TUICallKit_Swiftfunc initCallEngine() {let youSdkAppID: Int32 = 10_000_000_00 // 填写你的实际sdkAppIDlet testUserID = "testUserID" // 你的测试用户IDlet userSig = "xxxxxxx" // 你的测试用户ID对应的 userSig (从IM 控制台获取,看上面的截图)TUICallEngine.createInstance().`init`(youSdkAppID, userId: testUserID, userSig: userSig) {// enableIncomingBanner(true) 用于开启被叫时的来电横幅通知TUICallKit.createInstance().enableIncomingBanner(enable: true)} fail: { code, message inprint("initCallEngine failed: \\(code), \\(message ?? "")")}}
func startVideoCall() {TUICallKit.createInstance().calls(userIdList: ["liu100"], // 被叫用户 ID 列表。单人通话传一个元素;传多个则为群组通话mediaType: .video, // 通话类型:.video 视频通话、.audio 语音通话params: nil,completion: nil)}
func showChat(_ info: ConversationInfo) {// 在输入配置中关闭输入面板中的视频通话和音频通话功能let inputConfig = ChatMessageInputConfig(isShowVideoCall: false, isShowAudioCall: false)let chatPage = ChatPage(conversation: info, messageInputConfig: inputConfig, onBack: { [weak self] inself?.navigationController.popViewController(animated: true)})navigationController.pushViewController(chatPage, animated: true)}
TXLiteAVSDK_TRTC 库,不会发生符号冲突。可直接在 Podfile 文件中添加依赖,pod 'TUICallKit_Swift'
TXLiteAVSDK_Professional 库,会产生符号冲突。您可在 Podfile 文件中添加依赖,pod 'TUICallKit_Swift/Professional'
TXLiteAVSDK_Enterprise 库,会产生符号冲突。建议升级到 TXLiteAVSDK_Professional 后使用 TUICallKit_Swift/Professional。

#!/bin/sh# Strip invalid architecturesstrip_invalid_archs() {binary="$1"echo "current binary ${binary}"# Get architectures for current filearchs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"stripped=""for arch in $archs; doif ! [[ "${ARCHS}" == *"$arch"* ]]; thenif [ -f "$binary" ]; then# Strip non-valid architectures in-placelipo -remove "$arch" -output "$binary" "$binary" || exit 1stripped="$stripped $arch"fifidoneif [[ "$stripped" ]]; thenecho "Stripped $binary of architectures:$stripped"fi}APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"# This script loops through the frameworks embedded in the application and# removes unused architectures.find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORKdoFRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"strip_invalid_archs "$FRAMEWORK_EXECUTABLE_PATH"done









post_install do |installer|bitcode_strip_path = 'xcrun --find bitcode_strip'.chop!def strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)framework_path = File.join(Dir.pwd, framework_relative_path)command = "#{bitcode_strip_path} #{framework_path} -r -o #{framework_path}"puts "Stripping bitcode: #{command}"system(command)endframework_paths = ["/Pods/TXIMSDK_iOS/ImSDK.framework/ImSDK",]framework_paths.each do |framework_relative_path|strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)endend

文档反馈