You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI网络数据应用添加searchable搜索栏过滤自定义对象问题

SwiftUI 自定义对象列表实现.searchable本地搜索

问题背景

这是Greg Lim所著《Beginning Swift UI》中调用Github Web接口的SwiftUI练习扩展项目,项目仓库地址:GitProbe。

项目在原有练习基础上做了改动:将原代码中硬编码的查询目标改为可手动输入的入口,支持用户自定义要查询的用户。由于接口返回数据量较大,需要给结果列表添加.searchable修饰符,支持用户过滤已拉取的列表结果。

现有实现参考了基础字符串列表的搜索方案,但接口返回的JSON会被解码为自定义User对象组成的数组,直接套用字符串匹配逻辑无法正常工作,原有代码存在逻辑错误,需要调整实现。

原有代码问题

你写的searchResults计算属性和列表绑定逻辑有两个明显错误:

  • 搜索分支错误调用了fetchUsers.search(for: searchText),这个方法是发起网络请求重新拉取Github接口数据的方法,不是本地列表过滤逻辑,完全不符合本地筛选的需求
  • List组件的数据源仍然直接绑定了fetchUsers.users,没有使用你定义的searchResults计算属性,所以搜索框输入内容不会触发列表内容刷新

修正实现

直接在searchResults计算属性中实现本地过滤逻辑,匹配User对象的对应属性即可,同时将List的数据源替换为searchResults,修正后的UserView代码如下:

struct UserView: View {
    
    @State var username: String
    @ObservedObject var fetchUsers = FetchUsers()
    @State var searchText = ""
    
    var body: some View {
        List {
            ForEach(searchResults, id:\.self) { user in
                NavigationLink(user.login, destination: UserDetailView(user:user))
            }
        }.onAppear {
            self.fetchUsers.search(for: username)
        }
        .searchable(text: $searchText)
        .navigationTitle("Users")
    }

    /// 搜索结果计算属性
    private var searchResults: [User] {
        let trimmedSearchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        if trimmedSearchText.isEmpty {
            // 搜索内容为空时返回全量拉取到的用户列表
            return fetchUsers.users
        } else {
            // 本地匹配用户名,不区分大小写
            return fetchUsers.users.filter { user in
                user.login.localizedCaseInsensitiveContains(trimmedSearchText)
            }
        }
    }
}

扩展说明

  • 上述实现用localizedCaseInsensitiveContains做匹配,默认不区分大小写,符合常规搜索使用习惯,如果需要严格区分大小写,直接替换为contains即可
  • 如果需要支持多字段搜索,比如同时匹配用户名和用户ID,只需要在filter闭包中添加或判断条件即可,示例:
    return fetchUsers.users.filter { user in
        user.login.localizedCaseInsensitiveContains(trimmedSearchText) 
        || String(user.id).contains(trimmedSearchText)
    }
    
  • 如果需要实现输入时实时请求Github接口的远程搜索,而不是过滤本地已拉取的数据,需要给searchText添加onChange监听,加防抖处理后再调用网络请求方法,避免输入过程中频繁发起无效请求。

内容的提问来源于stack exchange,提问作者ethamoose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 01:36:32