iOS(SwiftUI)
本文会引导您在 TUIKit SwiftUI 上实现搜索。
注意:
开发环境要求
Xcode 15 及以上
iOS 15.0 及以上
前置条件
在构建界面之前,请确保您已经完成了以下 4 件事:
1. 在控制台创建了一个应用。
2. 在控制台创建了至少 2 个用户账号。
3. 集成了
TUIKit SwiftUI。4. 调用
LoginStore 的 login 接口登录组件。注意:
1. 每次启动应用,登录一次即可。
2. 请确保登录成功,我们建议您在登录成功的回调里进行下文的操作。
步骤说明
注意,如果直接使用示例代码,需要预填充以下参数:
sdkAppID,上文获取的 sdkAppID。userID,操作者的 userID,也就是 快速开始 中创建的 user1。userSig,操作者的 userSig,也就是 快速开始 中创建的 user1 的 userSig。App 启动即加载搜索入口 SearchBar,点击 SearchBar 输入搜索词触发搜索,示例代码如下:
// ContentView.swiftimport SwiftUIstruct ContentView: View {var body: some View {SearchPage()}}// SearchPage.swiftimport AtomicXimport AtomicXCoreimport SwiftUIpublic struct SearchPage: View {@StateObject private var themeState = ThemeState.shared@State private var isLoggedIn = false@State private var isLoggingIn = true@State private var loginError: String? = nilprivate let sdkAppID: Int32 = 1234567890 // TODO: Fill in the sdkAppID hereprivate let userID = "" // TODO: Fill in your userID hereprivate let userSig = "" // TODO: Fill in your generated userSig herepublic var body: some View {Group {if isLoggedIn {searchContentView} else if isLoggingIn {ProgressView("Logging in...")} else {VStack(spacing: 12) {Image(systemName: "exclamationmark.triangle").font(.system(size: 40)).foregroundColor(.orange)Text(loginError ?? "Login failed").foregroundColor(.secondary)}}}.environmentObject(themeState).onAppear {login()}}// MARK: - Search Contentprivate var searchContentView: some View {VStack(spacing: 0) {navigationBarViewDivider().background(.gray)// Add SearchBar to this page.SearchBar(onTapItem: { result inhandleSearchResult(result)}).padding(.vertical, 8)Spacer()}.background(themeState.colors.bgColorOperate.ignoresSafeArea(edges: .top))}// MARK: - Navigation Barprivate var navigationBarView: some View {HStack {Image(systemName: "magnifyingglass").font(.system(size: 24)).foregroundColor(.gray)Text("Search").font(.system(size: 17, weight: .semibold)).foregroundColor(themeState.colors.textColorPrimary)Spacer()}.padding(.horizontal, 16).frame(height: 44)}// MARK: - Handle Search Resultprivate func handleSearchResult(_ result: Any) {if let friendInfo = result as? FriendSearchInfo {// Handle friend search resultlet conversationID = ChatUtil.getC2CConversationID(friendInfo.userID)print(">>>>> Search result - Friend: \(friendInfo.userID), conversationID: \(conversationID)")} else if let groupInfo = result as? GroupSearchInfo {// Handle group search resultlet conversationID = ChatUtil.getGroupConversationID(groupInfo.groupID)print(">>>>> Search result - Group: \(groupInfo.groupID), conversationID: \(conversationID)")} else if let messageDict = result as? [String: Any],let messageInfo = messageDict["message"] as? MessageInfo,let conversationID = messageDict["conversationID"] as? String{// Handle message search result (from search detail view)let conversationName = messageDict["conversationName"] as? String ?? "Unknown"print(">>>>> Search result - Message in \(conversationName), conversationID: \(conversationID), messageID: \(messageInfo.id)")} else if let conversationDict = result as? [String: Any],let conversationID = conversationDict["conversationID"] as? String{// Handle conversation search result (from detail view)let conversationName = conversationDict["conversationName"] as? String ?? "Unknown"print(">>>>> Search result - Conversation: \(conversationName), conversationID: \(conversationID)")} else {print(">>>>> Search result - Unknown type: \(result)")}}// MARK: - Loginprivate func login() {guard !userSig.isEmpty else {isLoggingIn = falseloginError = "userSig is empty. Please fill in a valid userSig."return}// Login is required when page appears.LoginStore.shared.login(sdkAppID: sdkAppID, userID: userID, userSig: userSig) { result inswitch result {case .success:print(">>>>> SearchPage login success, userID: \(userID)")isLoggedIn = trueisLoggingIn = falsecase .failure(let error):print(">>>>> SearchPage login failed: \(error.code), \(error.message)")loginError = "Login failed: \(error.code), \(error.message)"isLoggingIn = false}}}}
运行效果如下:

注意:
上述示例代码中的 SearchPage 中的 handleSearchResult 目前仅打印搜索结果信息。实际使用时,您需要在此处实现页面跳转逻辑:根据搜索结果的类型(好友、群组、消息或会话),跳转到对应的聊天页面。如果搜索结果是消息类型,还可以在进入聊天页后自动定位到该条消息。
常见问题
如何搜索富媒体消息?
富媒体消息包含文件、图片、语音、视频消息。
对于文件消息,界面通常显示文件名,因此创建时可以设置
fileName 参数,作为被搜索的内容,如果 fileName 不设置则会从 filePath 提取文件名,并保存到本地和服务器。而对于图片、语音、视频消息,界面通常显示缩略图或时长,可以指定消息类型做分类搜索,但不能通过关键字搜索。
