简体   繁体   English

在tableView swift4中搜索JSON数据

[英]Search JSON data in tableView swift4

I am trying to show jsondata in to the tableView and search country from the searchBar but getting error in to the textDidChange function.我正在尝试将jsondata显示到tableView并从searchBar搜索country ,但在textDidChange函数中error

I want the user to enter three words into the searchBar then tableView will open and search data.我想用户输入三个字到searchBar ,然后tableView将打开和搜索数据。

struct country : Decodable {
    let name : String
    let capital : String
    let region : String
  }

class ViewController: UIViewController,UISearchBarDelegate {

    var isSearch : Bool = false
    var countries = [country]()
    var arrFilter:[String] = []

    @IBOutlet weak var tableview: UITableView!
    @IBOutlet weak var searchbar: UISearchBar!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableview.dataSource = self
        tableview.delegate = self
        searchbar.delegate = self

        let jsonurl = "https://restcountries.eu/rest/v2/all"
        let url = URL(string: jsonurl)

        URLSession.shared.dataTask(with: url!) { (data, response, error) in

            do{
                self.countries = try JSONDecoder().decode([country].self, from: data!)

            }
            catch{
                print("Error")
            }
            DispatchQueue.main.async {
                self.tableview.reloadData()
            }
            }.resume()
}

shows error into this part.在这部分显示错误。

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

    if searchText.characters.count == 0 {
        isSearch = false;
        self.tableview.reloadData()
    } else {
        arrFilter = countries.filter({ (text) -> Bool in
            let tmp: NSString = text
            let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
            return range.location != NSNotFound
        })
        if(arrFilter.count == 0){
            isSearch = false;
        } else {
            isSearch = true;
        }
        self.tableview.reloadData()
    }
  }

}

my table view part我的表视图部分

extension ViewController : UITableViewDelegate, UITableViewDataSource{
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if(isSearch){
       return arrFilter.count
    }
    else{
      return countries.coun
    }
}

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

    let cell = tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    if(isSearch){    
         cell.textLabel?.text = arrFilter[indexPath.row]    
    }else{
         cell.textLabel?.text = countries[indexPath.row].name.capitalized
    }
    return cell
  }
}
  • First of all do not use NSString in Swift and the Foundation rangeOfString API, use native String and native range(of .首先不要在 SwiftFoundation rangeOfString API 中使用NSString ,使用原生String和原生range(of .
  • Second of all never check for an empty string and for an empty array with .count == 0 .其次,永远不要检查空字符串和.count == 0的空数组。 There is isEmpty .isEmpty
  • Third of all please name structs and classes with a starting capital letter.第三,请以大写字母开头命名结构和类。 struct Country ... . struct Country ... .

The error occurs because you are filtering Country instances and actually you are looking for its name or its region .发生错误是因为您正在过滤Country实例,而实际上您正在寻找它的name或它的region

This is a pure Swift version of your code这是您代码的纯 Swift 版本

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

    if searchText.isEmpty {
        isSearch = false
    } else {
        arrFilter = countries.filter( $0.name.range(of: searchText, options: .caseInsensitive) != nil }
        isSearch = !arrFilter.isEmpty 
    }
    self.tableview.reloadData()
}

If you want to filter for name and region write如果要过滤nameregion写入

arrFilter = countries.filter( $0.name.range(of: searchText, options: .caseInsensitive) != nil 
                              || $0.region.range(of: searchText, options: .caseInsensitive) != nil }

With this syntax declare arrFilter使用此语法声明arrFilter

var arrFilter = [Country]()

and in cellForRow write并在cellForRow写入

let dataArray = isSearch ? arrFilter : countries
cell.textLabel?.text = dataArray[indexPath.row].name.capitalized 

You are getting country object of your array as a string so such an error occured.. Please do as below您正在以字符串形式获取数组的国家/地区对象,因此发生了这样的错误。请按以下步骤操作

    var arrFilter:[country] = [country]()

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

        let cell = tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        if(isSearch){    
        cell.textLabel?.text = arrFilter[indexPath.row].name.capitalized    
        }else{
             cell.textLabel?.text = countries[indexPath.row].name.capitalized
        }
        return cell
    }


    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            if searchText.characters.count == 0 {
                isSearch = false;
                self.tableview.reloadData()
            } else {
                arrFilter = countries.filter({ (country) -> Bool in

                    let tmp: NSString = NSString.init(string: country.name)
                    let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)

                    return range.location != NSNotFound
                })
                if(arrFilter.count == 0){
                    isSearch = false;
                } else {
                    isSearch = true;
                }
                self.tableview.reloadData()
            }
     }

First you can not assign a value type [Country] to [String].For example when assign a arrFilter at that time country.filter always return country type value not a string type.首先,您不能将值类型 [Country] 分配给 [String]。例如,当分配 arrFilter 时 country.filter 始终返回国家类型值而不是字符串类型。

use below code to helping you,使用下面的代码来帮助你,

var countries = [country]()
var arrFilter:[country] = [country]()

inside the viewdidLoad在 viewdidLoad 里面

override func viewDidLoad() {

    self.countries.append(country(name: "India", capital: "New Delhi", region: "Asia"))
    self.countries.append(country(name: "Indonesia", capital: "Jakarta", region: "region"))
    self.countries.append(country(name: "Australia", capital: "Canberra", region: "Austrialia"))
    // Do any additional setup after loading the view.
}

And

 self.arrFilter = self.countries.filter({ (country) -> Bool in
        let temp : NSString  = country.name as NSString //or you can use country.capital or country.region
        let range = temp.range(of: "ind", options: .caseInsensitive)
        print(range.location)
        print(range.length)
        print(temp)
        return range.location != NSNotFound
    })

Thanks谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM