有奖捉虫:行业应用 & 管理与支持文档专题 HOT

适用场景

TUIChat 提供了私信聊天(1V1)和群聊(Group)功能,支持对消息的多种操作,例如发送不同类型的消息、对消息长按点赞/回复/引用、查询消息已读回执详情等。
您可以仅集成 TUIChat 到您的 App 中。聊天界面使用场景非常广泛,例如房产中介咨询、在线医疗问诊、电商在线客服、保险远程定损等。 界面效果如下图所示:
经典版
简约版
RTL 语言
消息界面
发送多种类型消息






消息点赞/回复/引用
消息回复详情






消息已读回执
已读回执详情






消息界面 | 发送多种类型消息



消息点赞 | 回复



消息已读回执 | 已读回执详情



消息界面 | 发送多种类型消息



消息点赞 | 回复



消息已读回执 | 已读回执详情




开发环境要求

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 project
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '13.0'
# 防止 TUIChat 组件里的 *.xcassets 与您项目里面冲突。
install! 'cocoapods', :disable_input_output_paths => true

# 请使用您的真实项目名称替换 your_project_name
target 'your_project_name' do
use_frameworks!

# 开启 modular headers。请按需开启,开启后 Pod 模块才能使用 @import 导入。
# use_modular_headers!
# 集成聊天功能
pod 'TUIChat/UI_Classic'
end

#Pods config
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#Fix Xcode14 Bundle target error
config.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 -ld64
xcode_version = `xcrun xcodebuild -version | grep Xcode | cut -d' ' -f2`.to_f
if xcode_version >= 15
xcconfig_path = config.base_configuration_reference.real_path
xcconfig = File.read(xcconfig_path)
if xcconfig.include?("OTHER_LDFLAGS") == false
xcconfig = xcconfig + "\\n" + 'OTHER_LDFLAGS = $(inherited) "-ld64"'
else
if xcconfig.include?("OTHER_LDFLAGS = $(inherited)") == false
xcconfig = xcconfig.sub("OTHER_LDFLAGS", "OTHER_LDFLAGS = $(inherited)")
end
if xcconfig.include?("-ld64") == false
xcconfig = xcconfig.sub("OTHER_LDFLAGS = $(inherited)", 'OTHER_LDFLAGS = $(inherited) "-ld64"')
end
end
File.open(xcconfig_path, "w") { |file| file << xcconfig }
end
end
end
end
# Uncomment the next line to define a global platform for your project
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '13.0'
# 防止 TUIChat 组件里的 *.xcassets 与您项目里面冲突。
install! 'cocoapods', :disable_input_output_paths => true

# 请使用您的真实项目名称替换 your_project_name
target 'your_project_name' do
use_frameworks!

# 开启 modular headers。请按需开启,开启后 Pod 模块才能使用 @import 导入。
# use_modular_headers!

# 集成聊天功能
pod 'TUIChat/UI_Minimalist'
end

#Pods config
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#Fix Xcode14 Bundle target error
config.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 -ld64
xcode_version = `xcrun xcodebuild -version | grep Xcode | cut -d' ' -f2`.to_f
if xcode_version >= 15
xcconfig_path = config.base_configuration_reference.real_path
xcconfig = File.read(xcconfig_path)
if xcconfig.include?("OTHER_LDFLAGS") == false
xcconfig = xcconfig + "\\n" + 'OTHER_LDFLAGS = $(inherited) "-ld64"'
else
if xcconfig.include?("OTHER_LDFLAGS = $(inherited)") == false
xcconfig = xcconfig.sub("OTHER_LDFLAGS", "OTHER_LDFLAGS = $(inherited)")
end
if xcconfig.include?("-ld64") == false
xcconfig = xcconfig.sub("OTHER_LDFLAGS = $(inherited)", 'OTHER_LDFLAGS = $(inherited) "-ld64"')
end
end
File.open(xcconfig_path, "w") { |file| file << xcconfig }
end
end
end
end
说明:
如果您直接 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
Development Podfile
# Uncomment the next line to define a global platform for your project
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '13.0'
install! 'cocoapods', :disable_input_output_paths => true

# 请使用您的真实项目名称替换 your_project_name
target 'your_project_name' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
use_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"

# 其他 Pod
pod 'MJRefresh'
pod 'Masonry'
end

#Pods config
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#Fix Xcode14 Bundle target error
config.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 -ld64
xcode_version = `xcrun xcodebuild -version | grep Xcode | cut -d' ' -f2`.to_f
if xcode_version >= 15
xcconfig_path = config.base_configuration_reference.real_path
xcconfig = File.read(xcconfig_path)
if xcconfig.include?("OTHER_LDFLAGS") == false
xcconfig = xcconfig + "\\n" + 'OTHER_LDFLAGS = $(inherited) "-ld64"'
else
if xcconfig.include?("OTHER_LDFLAGS = $(inherited)") == false
xcconfig = xcconfig.sub("OTHER_LDFLAGS", "OTHER_LDFLAGS = $(inherited)")
end
if xcconfig.include?("-ld64") == false
xcconfig = xcconfig.sub("OTHER_LDFLAGS = $(inherited)", 'OTHER_LDFLAGS = $(inherited) "-ld64"')
end
end
File.open(xcconfig_path, "w") { |file| file << xcconfig }
end
end
end
end
注意:
使用本地集成方案时,如需升级时可进入 Github-TUIChat 升级。
获取最新的组件代码,覆盖本地目录如:TIMSDK/iOS/TUIKit/TUIChat。
当私有化修改和远端有冲突时,需要手动合并,处理冲突。
TUIChat 插件需要依赖 TUICore 的版本,务必确保插件版本和 "../TUIKit/TUICore/TUICore.spec"中的 spec.version 一致。
若您操作遇到错误,可查阅文末的常见问题。

组件登录

TUIChat 组件登录成功之后才能正常使用聊天功能。
其中,SDKAppID 需要在 即时通信 IM 控制台 创建并获取,userSig 需要按规则计算,详细步骤请参考文档 跑通 Demo
示例代码如下所示:
#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;
// 创建 chatVC
TUIBaseChatViewController *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;
// 创建 chatVC
TUIBaseChatViewController_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";
// 创建 chatVC
TUIBaseChatViewController *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";
// 创建 chatVC
TUIBaseChatViewController_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 architectures
strip_invalid_archs() {
binary="$1"
echo "current binary ${binary}"
# Get architectures for current file
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
stripped=""
for arch in $archs; do
if ! [[ "${ARCHS}" == *"$arch"* ]]; then
if [ -f "$binary" ]; then
# Strip non-valid architectures in-place
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
stripped="$stripped $arch"
fi
fi
done
if [[ "$stripped" ]]; then
echo "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 FRAMEWORK
do
FRAMEWORK_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 的符号冲突,都属于该问题。

解决方式:修改链接器配置
Build Settings 中的Other Linker Flags 种添加"-ld64",即可解决。 详情可参见 此文档

Rosetta 模拟器问题
使用苹果芯片(m1\\m2等系列芯片)时会遇到, 原因是包括 SDWebImage 在内的三方库,并未支持 xcframework,不过苹果依旧给出了适配办法,就是在模拟器上开启 Rosetta 设置, 一般情况下编译时会自动弹出 Rosetta 选项。

Xcode 15 开发者沙盒选项问题
Sandbox: bash(xxx) deny(1) file-write-create

当您使用 Xcode 15 创建一个新工程时, 可能会因为此选项导致编译运行失败,建议您关闭此选项。


CocoaPods 集成常见问题

使用远端集成时,Pod依赖版本不匹配问题
若您使用远端 Pods 集成时,出现 Podfile.lock 和 插件依赖的 TUICore 版本不一致时,
此时请删除 Podfile.lock 文件, 并使用 pod repo update 更新本地代码仓库, 之后使用 pod update 重新更新即可。

使用本地集成时,Pod依赖版本不匹配问题
若您使用DevelopPods集成时 出现 插件依赖的 TUICore 版本较新,但本地 Pod 依赖的版本号是 1.0.0
此时请您参见 Podfile_localTUICore.spec , 插件需要跟随版本,需要和 TUICore.spec 中一致,正常情况下我们会帮您修改为一致。
第一次使用本地集成时,建议您下载我们的示例 Demo 工程,将 Podfile 文件内容替换为 Podfile_local 的内容,执行 Pod update 后相互参照。