searchview returns 搜索时空白

searchview returns blank when I search

我是 Xcode 和 Swift 的新手,但理解即将到来。现在的问题是我有一个 table 视图,里面有一个搜索视图。当我 运行 代码时,数据从 api 正确接收到 table 视图,但是当我尝试进行搜索时,它的 returns 是一个空列表。

如何更正我的代码?

我的控制器:

 var clientDetails = [Client]()
var currentClientDetails = [Client]()

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "clients_list") as? ClientCellTableViewCell else { return UITableViewCell() }

    cell.nameLb.text = "Name: " + currentClientDetails[indexPath.row].CLNT_FULLNAME
    cell.emailLb.text = "Email: " + currentClientDetails[indexPath.row].CLNT_EMAIL
    cell.phonenumberLb.text = "Phone Number: " + currentClientDetails[indexPath.row].CLNT_PHONE
    cell.clientidLb.text = "ID: " + currentClientDetails[indexPath.row].CLNT_CODE
    return cell
}

override func viewDidLoad() {
    super.viewDidLoad()

    self.clientsTableView.delegate = self
    self.clientsTableView.dataSource = self

    fetchData()
    setUpSearchBar()
    alterLayout()
}

func alterLayout() {
    clientsTableView.tableHeaderView = UIView()
    // search bar in section header
    clientsTableView.estimatedSectionHeaderHeight = 50
    // search bar in navigation bar
    //navigationItem.leftBarButtonItem = UIBarButtonItem(customView: searchBar)
    navigationItem.titleView = searchBar
    searchBar.showsScopeBar = false // you can show/hide this dependant on your layout
    searchBar.placeholder = "Search Client by Name"
}

private func setUpSearchBar() {
    searchBar.delegate = self
}

func fetchData(){

    let myapiurl = URL(string: "https://fpay.com/api")

    guard let downloadURL = myapiurl else { return }
    URLSession.shared.dataTask(with: downloadURL) { data, urlResponse, error in
        guard let data = data, error == nil, urlResponse != nil else {
            DispatchQueue.main.async {
                let alert = UIAlertController(title: "Fofoofo Pay", message: "Please try again or check your internet connection", preferredStyle: .alert)
                let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
                alert.addAction(action)

                self.present(alert, animated: true, completion: nil)
            }
            return
        }
        print("JSON downloaded")
        do
        {
            let decoder = JSONDecoder()
            let downloadedJson = try decoder.decode(Client_details.self, from: data)
            self.clientDetails = downloadedJson.client_details
            self.currentClientDetails = self.clientDetails
            DispatchQueue.main.async {
                self.clientsTableView.reloadData()
            }
        } catch {
            print(error)
        }
    }.resume()
}

  // Search Bar
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        currentClientDetails = clientDetails.filter({ client -> Bool in
            switch searchBar.selectedScopeButtonIndex {
            case 0:
                if searchText.isEmpty { return true }
                return client.CLNT_FULLNAME.lowercased().contains(searchText.lowercased())
            default:
                return false
            }
        })
        clientsTableView.reloadData()
    }

客户class:

    Client_details: Codable {
    let client_details: [Client]

    init(client_details: [Client]) {
        self.client_details = client_details
    }
}

class Client:Codable {
    let CLNT_CODE:String
    let CLNT_FULLNAME:String
    let CLNT_PHONE:String
    let CLNT_EMAIL:String
    init(CLNT_CODE:String, CLNT_FULLNAME:String, CLNT_PHONE:String, CLNT_EMAIL:String) {
        self.CLNT_CODE = CLNT_CODE
        self.CLNT_FULLNAME = CLNT_FULLNAME
        self.CLNT_PHONE = CLNT_PHONE
        self.CLNT_EMAIL = CLNT_EMAIL
    }

这是固定的。我将 searchBar 函数中的代码更改为:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        currentClientDetails = clientDetails
        if searchText.isEmpty == false {
        currentClientDetails = clientDetails.filter({ [=10=].CLNT_FULLNAME.contains(searchText) })
        }

        clientsTableView.reloadData()
    }

现在returns只有搜索到的-区分大小写,不区分大小写,部分匹配,匹配开始,匹配结束。此外,当搜索字段为空时,它会显示所有数据。

我想借此机会向您详细介绍正在发生的事情,以便您可以继续学习并提高您的技能。所以你遇到的问题是你的 searchBar(_ textDidChange:...) 方法没有按照你期望的方式进行过滤。特别是这段代码。

currentClientDetails = clientDetails.filter({ client -> Bool in
        switch searchBar.selectedScopeButtonIndex {
        case 0:
            if searchText.isEmpty { return true }
            return client.CLNT_FULLNAME.lowercased().contains(searchText.lowercased())
        default:
            return false
        }
    })

没有产生任何结果的可能原因有两个。原因 #1,您的 client.CLNT_FULLNAME 是 returning "" 或者您的方法总是 returning false 因为第一个元素是 "" 或命中 default: 其中 return 是错误的。

根据您提供的代码,client 永远不会被排序。这意味着每次 searchBar(_ textDidChange:...) 方法被命中时它总是一样的,永远不会在你的闭包内部改变。因此,为了解决这个问题,让我们分解解决方案。

解决方案

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        currentClientDetails = clientDetails.filter({ [=11=].CLNT_FULLNAME.contains(searchText) })
        clientsTableView.reloadData()
    }

那么,这个闭包内部发生了什么与您拥有的是什么? .filter() 到底做了什么,闭包是如何工作的? .filter() 有两个版本,在您的情况下,您使用的是顺序闭包。这意味着它将 return 基于给定谓词(公式)的 [object]

这里给出的谓词是什么,它有什么特别之处[=22=].filter() 中给出的谓词正在检查 [object] 中的每个元素,并且 return 为每个元素判断真假。如果它包含部分或全部匹配项,则为真,否则为假。一旦闭包完成,或者 序列 完成,它 return 就是一个给定的对象。在您的情况下,它似乎是 [client].

我喜欢将 .filter() 方法视为一种 for _ in 0..X 循环,当您使用上述那些 [=22=] 看起来很花哨的东西时,这是一个需要考虑的重要概念。本质上 [=22=] 是说序列中的第一个元素与什么相比?或 client[0] 与什么相比。这将是初始序列,它将一直持续到序列完成,也就是 for _ in 0...X.count.

的计数

我希望这能给您一些考虑并让您继续编码。感谢您提出深思熟虑的问题并积极参与解决问题。