适用场景
TUIChat 提供了私信聊天(1V1)和群聊(Group)功能,支持对消息的多种操作,例如发送不同类型的消息、对消息长按点赞/回复/引用、查询消息已读回执详情等。
您可以仅集成 TUIChat 到您的 App 中。聊天界面使用场景非常广泛,例如房产中介咨询、在线医疗问诊、电商在线客服、保险远程定损等。
界面效果如下图所示:
消息界面 | 发送多种类型消息 |
| |
消息点赞/回复/引用 | 消息回复详情 |
| |
消息已读回执 | 已读回执详情 |
| |
消息界面 | 发送多种类型消息 |
|
消息点赞 | 回复 |
|
消息已读回执 | 已读回执详情 |
|
消息界面 | 发送多种类型消息 |
|
消息点赞 | 回复 |
|
消息已读回执 | 已读回执详情 |
|
开发环境要求
Xcode 10 及以上
iOS 9.0 及以上
通过 Pod 集成 TUIChat 源码
我们为您提供了两种 Podfile 集成方式:拉取远程 CocoaPods 集成(方式一)和 Development Pods 本地集成(方式二),这两种方式的优劣如下:
拉取远程 CocoaPods 集成(方式一) 适合无源码修改时的集成:
优点: 当 TUIChat 有版本更新时您只需再次 Pod update 即可完成更新。
缺点: 当您有源码修改时,使用 Pod update 更新时,新版本的 TUIChat 会覆盖您的修改。
Development Pods 本地集成(方式二) 适合有涉及源码自定义修改的客户:
优点: 当您有自己的 git 仓库时,可以跟踪修改,并且修改源码后,使用 Pod update 更新(其他非本地集成 Pod)时,不会覆盖您的修改。
缺点: 您需要手动从 TUIChat 源码 覆盖您本地 TUIChat 文件夹进行更新。
方式一:拉取远程 CocoaPods 集成(无源码修改时推荐)
# Uncomment the next line to define a global platform for your projectsource 'https://github.com/CocoaPods/Specs.git'platform :ios, '13.0'# 防止 TUIChat 组件里的 *.xcassets 与您项目里面冲突。install! 'cocoapods', :disable_input_output_paths => true# 请使用您的真实项目名称替换 your_project_nametarget 'your_project_name' douse_frameworks!# 开启 modular headers。请按需开启,开启后 Pod 模块才能使用 @import 导入。# use_modular_headers!# 集成聊天功能pod 'TUIChat/UI_Classic'end#Pods configpost_install do |installer|installer.pods_project.targets.each do |target|target.build_configurations.each do |config|#Fix Xcode14 Bundle target errorconfig.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"config.build_settings['ENABLE_BITCODE'] = "NO"config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "13.0"#Fix Xcode15 other links flag -ld64xcode_version = `xcrun xcodebuild -version | grep Xcode | cut -d' ' -f2`.to_fif xcode_version >= 15xcconfig_path = config.base_configuration_reference.real_pathxcconfig = File.read(xcconfig_path)if xcconfig.include?("OTHER_LDFLAGS") == falsexcconfig = xcconfig + "\\n" + 'OTHER_LDFLAGS = $(inherited) "-ld64"'elseif xcconfig.include?("OTHER_LDFLAGS = $(inherited)") == falsexcconfig = xcconfig.sub("OTHER_LDFLAGS", "OTHER_LDFLAGS = $(inherited)")endif xcconfig.include?("-ld64") == falsexcconfig = xcconfig.sub("OTHER_LDFLAGS = $(inherited)", 'OTHER_LDFLAGS = $(inherited) "-ld64"')endendFile.open(xcconfig_path, "w") { |file| file << xcconfig }endendendend
# Uncomment the next line to define a global platform for your projectsource 'https://github.com/CocoaPods/Specs.git'platform :ios, '13.0'# 防止 TUIChat 组件里的 *.xcassets 与您项目里面冲突。install! 'cocoapods', :disable_input_output_paths => true# 请使用您的真实项目名称替换 your_project_nametarget 'your_project_name' douse_frameworks!# 开启 modular headers。请按需开启,开启后 Pod 模块才能使用 @import 导入。# use_modular_headers!# 集成聊天功能pod 'TUIChat/UI_Minimalist'end#Pods configpost_install do |installer|installer.pods_project.targets.each do |target|target.build_configurations.each do |config|#Fix Xcode14 Bundle target errorconfig.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"config.build_settings['ENABLE_BITCODE'] = "NO"config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "13.0"#Fix Xcode15 other links flag -ld64xcode_version = `xcrun xcodebuild -version | grep Xcode | cut -d' ' -f2`.to_fif xcode_version >= 15xcconfig_path = config.base_configuration_reference.real_pathxcconfig = File.read(xcconfig_path)if xcconfig.include?("OTHER_LDFLAGS") == falsexcconfig = xcconfig + "\\n" + 'OTHER_LDFLAGS = $(inherited) "-ld64"'elseif xcconfig.include?("OTHER_LDFLAGS = $(inherited)") == falsexcconfig = xcconfig.sub("OTHER_LDFLAGS", "OTHER_LDFLAGS = $(inherited)")endif xcconfig.include?("-ld64") == falsexcconfig = xcconfig.sub("OTHER_LDFLAGS = $(inherited)", 'OTHER_LDFLAGS = $(inherited) "-ld64"')endendFile.open(xcconfig_path, "w") { |file| file << xcconfig }endendendend
说明:
如果您直接
pod 'TUIChat'
,不指定经典版或简约版,默认会集成两套版本 UI 组件。 如果您使用的是 Swift,请开启
use_modular_headers!
,并将头文件引用改成 @import 模块名形式引用。执行以下命令,安装 TUIChat 组件。
pod install
如果无法安装 TUIChat 最新版本,执行以下命令更新本地的 CocoaPods 仓库列表。
pod repo update
之后执行以下命令,更新组件库的 Pod 版本。
pod update
集成 TUIChat 组件后的项目结构:
注意:
若您操作遇到错误,可查阅文末的常见问题。
方式二:Development Pods 本地集成(有源码修改时推荐)
1. 从 GitHub 下载 TUIChat 源码。直接拖入您的工程目录下,如:
TestTUIKitIM/TUIKit/TUIChat
。
2. 修改您 Podfile 中每个组件的本地路径, 路径修改为 TUIChat 文件夹相对您工程 Podfile 文件的路径。
例如 Demo 中的 pod 'TUIChat', :path => "./TUIKit/TUIChat"
说明:
上例中的 TUIChat 文件夹位于 TUIKit 的子目录,此时我们使用 pod 'TUIChat', :path => "./TUIKit/TUIChat"
其他相对路径的表示如下:
父目录: pod 'TUIChat', :path => "../TUIKit/TUIChat"
当前目录: pod 'TUIChat', :path => "/TUIKit/TUIChat"
子目录: pod 'TUIChat', :path => "./TUIKit/TUIChat"
3. 修改完成后
pod update
# Uncomment the next line to define a global platform for your projectsource 'https://github.com/CocoaPods/Specs.git'platform :ios, '13.0'install! 'cocoapods', :disable_input_output_paths => true# 请使用您的真实项目名称替换 your_project_nametarget 'your_project_name' do# Uncomment the next line if you're using Swift or would like to use dynamic frameworksuse_frameworks!use_modular_headers!# 注意:使用本地集成方案时,如需升级时需要从 https://github.com/TencentCloud/TIMSDK/tree/master/iOS/TUIKit/TUIChat# 获取最新的组件代码,放置在本地指定目录下,如/TIMSDK/ios/TUIKit/TUIChat# 注意:当私有化修改和远端有冲突时,需要手动合并,处理冲突。# 集成基础库(必选)pod 'TUICore', :path => "../TUIKit/TUICore"pod 'TIMCommon', :path => "../TUIKit/TIMCommon"# 集成聊天功能pod 'TUIChat', :path => "../TUIKit/TUIChat"# 其他 Podpod 'MJRefresh'pod 'Masonry'end#Pods configpost_install do |installer|installer.pods_project.targets.each do |target|target.build_configurations.each do |config|#Fix Xcode14 Bundle target errorconfig.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"config.build_settings['ENABLE_BITCODE'] = "NO"config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "13.0"#Fix Xcode15 other links flag -ld64xcode_version = `xcrun xcodebuild -version | grep Xcode | cut -d' ' -f2`.to_fif xcode_version >= 15xcconfig_path = config.base_configuration_reference.real_pathxcconfig = File.read(xcconfig_path)if xcconfig.include?("OTHER_LDFLAGS") == falsexcconfig = xcconfig + "\\n" + 'OTHER_LDFLAGS = $(inherited) "-ld64"'elseif xcconfig.include?("OTHER_LDFLAGS = $(inherited)") == falsexcconfig = xcconfig.sub("OTHER_LDFLAGS", "OTHER_LDFLAGS = $(inherited)")endif xcconfig.include?("-ld64") == falsexcconfig = xcconfig.sub("OTHER_LDFLAGS = $(inherited)", 'OTHER_LDFLAGS = $(inherited) "-ld64"')endendFile.open(xcconfig_path, "w") { |file| file << xcconfig }endendendend
注意:
使用本地集成方案时,如需升级时可进入 Github-TUIChat 升级。
获取最新的组件代码,覆盖本地目录如:TIMSDK/iOS/TUIKit/TUIChat。
当私有化修改和远端有冲突时,需要手动合并,处理冲突。
TUIChat 插件需要依赖 TUICore 的版本,务必确保插件版本和 "../TUIKit/TUICore/TUICore.spec"中的 spec.version 一致。
若您操作遇到错误,可查阅文末的常见问题。
组件登录
TUIChat 组件登录成功之后才能正常使用聊天功能。
示例代码如下所示:
#import "TUILogin.h"- (void)loginSDK:(NSString *)userID userSig:(NSString *)sig succ:(TSucc)succ fail:(TFail)fail {[TUILogin login:SDKAppID userID:userID userSig:sig succ:^{NSLog(@"登录成功");} fail:^(int code, NSString *msg) {NSLog(@"登录失败");}];}
跳转到聊天界面
您可以直接从您的 App 界面,跳转到 TUIChat 聊天界面。初始化聊天界面时,需要上层传入当前聊天界面对应的会话信息。
示例代码如下所示:
// 1v1 会话仅传 userID,群组会话仅传 groupID。- (void)pushToChatViewController:(NSString *)groupID userID:(NSString *)userID {// 创建会话信息TUIChatConversationModel *conversationData = [[TUIChatConversationModel alloc] init];conversationData.userID = userID;conversationData.groupID = groupID;// 创建 chatVCTUIBaseChatViewController *chatVC = nil;if (conversationData.userID.length > 0) {chatVC = [[TUIC2CChatViewController alloc] init];} else if (conversationData.groupID.length > 0) {chatVC = [[TUIGroupChatViewController alloc] init];}chatVC.conversationData = conversationData;[self.navigationController pushViewController:chatVC animated:YES];}
// 1v1 会话仅传 userID,群组会话仅传 groupID。- (void)pushToChatViewController:(NSString *)groupID userID:(NSString *)userID {// 创建会话信息TUIChatConversationModel *conversationData = [[TUIChatConversationModel alloc] init];conversationData.userID = userID;conversationData.groupID = groupID;// 创建 chatVCTUIBaseChatViewController_Minimalist *chatVC = nil;if (conversationData.userID.length > 0) {chatVC = [[TUIC2CChatViewController_Minimalist alloc] init];} else if (conversationData.groupID.length > 0) {chatVC = [[TUIGroupChatViewController_Minimalist alloc] init];}chatVC.conversationData = conversationData;[self.navigationController pushViewController:chatVC animated:YES];}
集成聊天窗口到自己的页面中
您也可以将 TUIChat 聊天界面,嵌入到自己控制器的 View 中。
示例代码如下所示:
#import "TUIC2CChatViewController.h"#import "TUIGroupChatViewController.h"// ChatViewController 为您自己的 ViewController@implementation ChatViewController- (void)viewDidLoad {// 创建会话信息TUIChatConversationModel *conversationData = [[TUIChatConversationModel alloc] init];// 1v1 会话仅传 userID,群组会话仅传 groupID。conversationData.userID = @"userID";conversationData.groupID = @"groupID";// 创建 chatVCTUIBaseChatViewController *chatVC = nil;if (conversationData.groupID.length > 0) {chatVC = [[TUIGroupChatViewController alloc] init];} else if (conversationData.userID.length > 0) {chatVC = [[TUIC2CChatViewController alloc] init];}[chatVC setConversationData:conversationData];// 把 chatVC 添加到自己的 ViewController 上[self addChildViewController:vc];[self.view addSubview:vc.view];}@end
#import "TUIC2CChatViewController_Minimalist.h"#import "TUIGroupChatViewController_Minimalist.h"// ChatViewController 为您自己的 ViewController@implementation ChatViewController- (void)viewDidLoad {// 创建会话信息TUIChatConversationModel *conversationData = [[TUIChatConversationModel alloc] init];// 1v1 会话仅传 userID,群组会话仅传 groupID。conversationData.userID = @"userID";conversationData.groupID = @"groupID";// 创建 chatVCTUIBaseChatViewController_Minimalist *chatVC = nil;if (conversationData.groupID.length > 0) {chatVC = [[TUIGroupChatViewController_Minimalist alloc] init];} else if (conversationData.userID.length > 0) {chatVC = [[TUIC2CChatViewController_Minimalist alloc] init];}[chatVC setConversationData:conversationData];// 把 chatVC 添加到自己的 ViewController 上[self addChildViewController:vc];[self.view addSubview:vc.view];}@end
常见问题
上架常见问题
上架 Appstore 时打包失败,提示 Unsupported Architectures。
问题现象如下图,打包时提示 ImSDK_Plus.framework 中包含了 Appstore 不支持的 x86_64 模拟器版本。该问题是由于 IMSDK 为了方便开发者调试,发布时会默认带上模拟器版本。
您可以按照下面的步骤,在打包时去掉模拟器版本:
1.1 选中您工程的 Target,并点击 Build Phases 选项,在当前面板中添加 Run Script;
1.2 在新增的 Run Script 中,添加如下脚本:
#!/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
Xcode15 集成常见问题
[Xcodeproj] Unknown object version (60). (RuntimeError)
使用 Xcode15 创建新工程来集成 TUIKit 时,输入pod install 后,可能会遇到此问题,原因是使用了较旧版本的 CocoaPods ,此时有两种解决办法:
解决方式一: 修改 Xcode 工程的 Project Format 版本。
解决方式二: 升级本地的 CocoaPods 版本,升级方式本文不再赘述。
您可以在终端输入 pod --version 查看当前的 Pods 版本。
-ld64链接器问题
Assertion failed: (false && "compact unwind compressed function offset doesn't fit in 24 bits"), function operator(), file Layout.cpp
或是使用 XCode15 集成 TUIRoom 时,因最新链接器导致 TUIRoomEngine 的符号冲突,都属于该问题。
解决方式:修改链接器配置
Rosetta 模拟器问题
使用苹果芯片(m1\\m2等系列芯片)时会遇到, 原因是包括 SDWebImage 在内的三方库,并未支持 xcframework,不过苹果依旧给出了适配办法,就是在模拟器上开启 Rosetta 设置, 一般情况下编译时会自动弹出 Rosetta 选项。
Xcode 15 开发者沙盒选项问题
Sandbox: bash(xxx) deny(1) file-write-create
当您使用 Xcode 15 创建一个新工程时, 可能会因为此选项导致编译运行失败,建议您关闭此选项。
CocoaPods 集成常见问题
使用远端集成时,Pod依赖版本不匹配问题
此时请删除 Podfile.lock 文件, 并使用 pod repo update 更新本地代码仓库, 之后使用 pod update 重新更新即可。
使用本地集成时,Pod依赖版本不匹配问题
第一次使用本地集成时,建议您下载我们的示例 Demo 工程,将 Podfile 文件内容替换为 Podfile_local 的内容,执行 Pod update 后相互参照。