【问题标题】:Filter array that contains optional - SearchBar包含可选的过滤器数组 - SearchBar
【发布时间】:2019-01-20 03:03:00
【问题描述】:

只是后见之明,让您了解我的问题。我目前正在为我在设备上保存 GuestList CoreData 的事件编写 iOS 应用程序。

在 viewDidLoad 上,它将获取 coredata 对象并将其放入 [GuestDetails] 数组中

现在Guestdetail对象结构如下:

private(set) public var guestFirstName: String
private(set) public var guestLastName: String?
private(set) public var guestEmail: String?
private(set) public var guestPhone: String?
private(set) public var guestUUID: UUID
private(set) public var guestBarcode: String?
private(set) public var guestCheckedIn: Bool

只有名字、UUID 和 checkinStatus 是强制性的。我已经设置了通过 JSON 添加,但现在我的问题出在我的 GuestListViewController 上,我有一个搜索栏

我正在使用以下代码和数组来确保我可以过滤。 我有另一个名为

的数组
searchResultArray = [GuestDetails]()

所以基本上我会将我所有的客人详细信息复制到 searchResultArray,这就是 tableView 从中获取其来源的那个。

现在作为搜索的一部分,我使用了在 appcoda 上找到的这段代码

searchResultArray = guestData.filter({guestData -> Bool in
   (guestData.guestFirstName.lowercased().contains(searchText.lowercased())) || 
   (guestData.guestLastName?.lowercased().contains(searchText.lowercased()))! ||
   (guestData.guestBarcode?.contains(searchText))!
})

问题是我的应用程序崩溃了,如果我只按名字搜索它不会崩溃,因为它们被强制解包很好,但是如果我添加代码来搜索姓氏或条形码,它会崩溃。我知道这可能是因为明确解包,但 xcode 不允许我不解包。

  • 我尝试过使用地图(这没有帮助,除非我对它不够熟悉),
  • 我已经尝试过 .compact(但我无法让它工作,因为我不确定它如何访问 GuestDetail 对象的内部以删除 nil)

  • 问题是 [GuestDetails] 的数组本身不会包含 null,GuestDetails 对象中的某些详细信息可能会导致它崩溃。

我的问题是,如何让它通过名字(已经可能)、姓氏和条形码进行搜索?

谢谢,我希望这个问题足够详细。

【问题讨论】:

    标签: ios arrays swift core-data


    【解决方案1】:

    这是一个有趣的小问题,所以让我们概括一下。这是我们的测试数据,可与您的 GuestDetails 数组相媲美:

    struct S {
        var s1 : String
        var s2 : String?
        var s3 : String?
    }
    
    var array = [S]()
    array.append(S(s1: "test", s2: "yo", s3: "ha"))
    array.append(S(s1: "test", s2: nil, s3: nil))
    array.append(S(s1: "Howdy", s2: "Bonjour", s3: "Hello"))
    
    let target = "hello"
    

    有些 S 属性是可选的,有些则不是。

    所以问题是:使用不区分大小写的比较,将array 过滤到any S 属性包含我们的target 字符串的那些元素。

    我们可以在一个语句中做到这一点:

    let filteredArray = array.filter {
        [$0.s1,$0.s2,$0.s3].compactMap {$0}
            .map {$0.localizedCaseInsensitiveContains(target)}
            .contains(true)
    }
    

    它没有@Ladislav 写的那么有效,因为即使我们找到了我们的字符串,我们仍然在map 内部循环。但效率低下可能并不显着。

    【讨论】:

      【解决方案2】:

      我会避免像这样使用强制展开:

      searchResultArray = guestData.filter({guestData -> Bool in
          let searchLowercased = searchText.lowercased()
          if guestData.guestFirstName.lowercased().contains(searchLowercased) {
              return true
          }
      
          if let guestLastName = guestData.guestLastName, guestLastName.lowercased().contains(searchLowercased) {
              return true
          }
      
          if let guestBarcode = guestData.guestBarcode, guestBarcode.lowercased().contains(searchLowercased) {
              return true
          }
      
          return false
      })
      

      从 cmets 回答您的问题:您不必在可选项上使用 ? 运算符,因为我们使用可选绑定 if let 语法。比如:

      if let guestLastName = guestData.guestLastName 如果guestData.guestLastNamenil,那么我们就会跳出这个if statement。然后你会在if statement 中看到,,只有当guestData.guestLastName 不是nil 时,我们才会传递这个逗号,这就是为什么我们可以使用guestLastName 未包装的变量String 并且不再是可选String?,然后我们会继续检查搜索词是否与guestLastNamereturn true 匹配。

      请阅读:if let , if var, guard let,guard var and defer statements in swift

      如果您碰巧将另一个属性添加到您的数据中并避免这样做if else,那会更好,您可以执行以下操作:

      searchResultArray = guestData.filter({guestData -> Bool in
          let searchLowercased = searchText.lowercased()
          let matches:[String?] = [guestData.guestFirstName, guestData.guestLastName, guestData.guestBarcode]
          let nonNilElements = matches.compactMap { $0 }
      
          for element in nonNilElements {
              if element.lowercased().contains(searchLowercased) {
                  return true
              }
          }
          return false
      })
      

      【讨论】:

      • let guestLastname = guestData.guestLastName 后面是逗号吗?因为 xcode 不允许我这样做
      • 哦,确实如此。这种语法叫什么?对不起,我很新
      • 它有效!它可以很好地编译和搜索!你能向我解释一下这种语法叫什么吗?在哪里添加逗号?所以我可以研究并学习
      • @Ladislav 要进行一些改进,请使用??localizedCaseInsensitiveCompare。请参阅我的“答案”。 (不是为了和你的答案竞争,但我不能不回答就发布代码。)
      猜你喜欢
      • 2021-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 2019-07-30
      • 2021-12-10
      • 1970-01-01
      相关资源
      最近更新 更多