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

Swift中如何访问嵌套结构体属性供UISearchBar搜索使用

UITableView 嵌套结构体搜索问题排查与修复

问题场景

当前表格分2个分区展示嵌套结构体数据,结构体定义如下:

struct ReceiveInResponse: Codable {
    var result: [ReceiveIn]
}

struct ReceiveIn: Codable {
    var section: String
    var items: [ReceiveInComp]

    enum CodingKeys: String, CodingKey {
        case section = "Section"
        case items
    }
}

struct ReceiveInComp: Codable {
   let owner, barcode, quantity: String
   let resultDescription, status: String

   enum CodingKeys: String, CodingKey {
      case owner = "Owner"
      case barcode = "Barcode"
      case quantity = "Quantity"
      case resultDescription = "Description"
      case status = "Status"
   }
}

实现barcode字段搜索时触发报错:Type '[ReceiveInComp]' has no member 'barcode',修复报错后又出现搜索结果重复的问题。

报错根因

两种错误写法的本质问题都是类型混淆:

  • ReceiveIn的items属性是[ReceiveInComp]类型,也就是ReceiveInComp元素组成的数组,barcode是数组内单个元素的属性,数组本身不存在这个属性,直接写myitems.barcode必然报错
  • 第一种写法用switch .barcode是枚举关联值的匹配语法,myitems是数组类型,不是枚举,语法完全不适用
  • 后续遍历item匹配时出现重复条目,是因为每匹配到一个符合条件的item就把整个分区对象追加到过滤列表,一个分区下如果有多个匹配item,同一个分区就会被多次添加,造成重复。

正确实现代码

根据展示需求二选一即可:

方案1:匹配到条目时保留整个分区的所有内容

只要分区下存在任意一个barcode匹配搜索词的条目,就把整个分区加入过滤列表,不会重复添加:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    self.filteredList.removeAll()
    let searchKeyword = searchText.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
    
    // 搜索词为空时返回全量数据
    guard !searchKeyword.isEmpty else {
        self.filteredList = self.ReviewList
        self.tableView.reloadData()
        return
    }
    
    for sectionItem in self.ReviewList {
        // 检查当前分区是否存在匹配项,只要有一个匹配就保留分区,仅追加一次
        let isContainMatch = sectionItem.items.contains { comp in
            comp.barcode.lowercased().contains(searchKeyword)
        }
        if isContainMatch {
            self.filteredList.append(sectionItem)
        }
    }
    self.tableView.reloadData()
}

方案2:搜索结果仅展示分区下匹配的条目

匹配时只保留分区内符合搜索条件的item,不展示同分区下的无关条目:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    self.filteredList.removeAll()
    let searchKeyword = searchText.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
    
    guard !searchKeyword.isEmpty else {
        self.filteredList = self.ReviewList
        self.tableView.reloadData()
        return
    }
    
    for sectionItem in self.ReviewList {
        // 筛选当前分区下所有匹配的条目
        let matchedComps = sectionItem.items.filter { comp in
            comp.barcode.lowercased().contains(searchKeyword)
        }
        // 有匹配项时才把处理后的分区加入列表,避免空分区、重复分区
        if !matchedComps.isEmpty {
            var filteredSection = sectionItem
            filteredSection.items = matchedComps
            self.filteredList.append(filteredSection)
        }
    }
    self.tableView.reloadData()
}

注意:如果ReviewList里的ReceiveIn实例是let常量,方案2里需要把ReceiveIn的items属性从let改为var,或者自定义构造方法生成新的实例。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:01:46