Как создать searchBar глобальный поиск для значения кодируемого массива JSON с помощью Swift 4.2? - PullRequest
0 голосов
/ 19 февраля 2019

Мой сценарий, я загружаю JSON данные в tableview с помощью структуры Codable.Здесь я пытаюсь добавить Searchbar, используя storyboard.Я не знаю, как синхронизировать данные self.tableArray с панелью поиска filtered array.Пожалуйста, предоставьте некоторую идею.

МОЯ кодируемая структура

struct Root: Codable {
    let data: [Datum]
}

struct Datum: Codable {
    let id, userID, country, card: Int
    let category: Int
    let title, description: String
    let createDate
    let user: User

    enum CodingKeys: String, CodingKey {
        case id
        case userID = "user_id"
        case country, card, category, title, description
        case createDate = "create_date"

    }
}

struct User: Codable {
    let firstname, lastname: String
}

Мой код JSON

do {
          let result = try JSONDecoder().decode(Root.self, from:data!)
          self.tableArray = result.data

} catch {
          print(error)
          self.tableArray = []
}

Мой код просмотра таблицы

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //return filteredData.count
        return tableArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

      let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! CustomTableViewCell

      let item = tableArray[indexPath.row]
      cell.name_label.text = ("\(item.user.firstname) " + "\(item.user.lastname)")
      cell.date_label.text = item.createDate

       return cell
}

Код панели поиска

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        // When there is no text, filteredData is the same as the original data
        // When user has entered text into the search box
        // Use the filter method to iterate over all items in the data array
        // For each item, return true if the item should be included and false if the
        // item should NOT be included
        filteredData = searchText.isEmpty ? names : names.filter({(dataString: String) -> Bool in
            // If dataItem matches the searchText, return true to include it
            return dataString.range(of: searchText, options: .caseInsensitive) != nil
        })
        tableView.reloadData()
    }

1 Ответ

0 голосов
/ 19 февраля 2019

Сначала нужно делегировать панель поиска, поэтому добавьте ее UISearchBarDelegate.В этом методе есть функция, которая проверяет, изменился текст в строке поиска или нет.Это

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { }

Но сначала вам нужно объявить переменную.

var isSearching = false

и добавить эту функцию

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    if searchBar.text == nil || searchBar.text == "" { // 



        isSearching = false
        view.endEditing(true)
        tableView.reloadData()
    }
    else {
        isSearching = true
        newArray = tableArray.filter({ value -> Bool in
            guard let text =  searchBar.text else { return false}
           return value.title.contains(text) // According to title from JSON

        })
        tableView.reloadData()
    }
}

newArray - это тот же tableArrayно он пустой.

Вы должны проверить ALS numberOfRowsInSection.Если вы не вносите изменения, это может привести к ошибке, такой как Index of out of range

Изменить ее

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if isSearching {
        return newArray.count
    }
    else {
           return self.tableArray.count
     }




    return 0
}

ОБНОВЛЕНИЕ : Я думаю, что проблема в этой части. Вам нужнодобавьте isSearching здесь также

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

  let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! CustomTableViewCell
   if isSearching{ 
   // Need to change according to newArray
   let item = newArray[indexPath.row]
   cell.name_label.text = ("\(item.user.firstname) " + "\(item.user.lastname)")
  cell.date_label.text = item.createDate

  }
  else {
  let item = tableArray[indexPath.row]
  cell.name_label.text = ("\(item.user.firstname) " + "\(item.user.lastname)")
  cell.date_label.text = item.createDate
  }
   return cell

}

...