简体   繁体   English

使用 struct Array 实现 Swift/iOS searchBar 时遇到问题

[英]Trouble implementing Swift/iOS searchBar with struct Array

I've got a struct Array that I'm using to populate my tableview.我有一个结构数组,我用它来填充我的表格视图。 But I am unable to get my searchBar to work correctly.但我无法让我的 searchBar 正常工作。 My original searchBar code was created when I was using a more "basic" array.我最初的 searchBar 代码是在我使用更“基本”的数组时创建的。 After converting to struct it no longer works.转换为 struct 后,它不再起作用。 I am getting 3 errors from Xcode.我从 Xcode 收到 3 个错误。 I've identified the errors in the code with // <-- ERROR.我已经用 // <-- ERROR 标识了代码中的错误。 Thanks for your help!谢谢你的帮助!

import UIKit

struct Material {
    var name : String
    var lbft : String
    var gcm : String
}

class ViewController: UIViewController {

    @IBOutlet weak var searchBar: UISearchBar!

    @IBOutlet var tableView: UITableView!

    let materialData = [
        Material(name: "Acetaminohen Powder, Unmilled",    lbft: "43",    gcm: "0.688794"),
        Material(name: "Acetylene Black, 100% Compressed",    lbft: "35",    gcm: "0.560646"),
        Material(name: "Acetylsalicyic Acid",    lbft: "20",    gcm: "0.320369"),
        Material(name: "Acrylamide",    lbft: "34",    gcm: "0.54463"),
        Material(name: "Acrylic Granules, Coarse",    lbft: "40",    gcm: "0.64"),
        Material(name: "Acrylic Granules, Fine",    lbft: "36",    gcm: "0.58"),
        Material(name: "Acrylonitrile Butadien Styrene (Abs) Resin",    lbft: "50",    gcm: "0.8"),
        Material(name: "Acrylonitrile Butadiene Styrene (Abs) Granules",    lbft: "36",    gcm: "0.58"),
        Material(name: "Activated Alumina",    lbft: "42.5",    gcm: "0.68"),
        Material(name: "Activated Carbon",    lbft: "32.5",    gcm: "0.52"),
        Material(name: "Actylene Black",    lbft: "45.5",    gcm: "0.73"),
        Material(name: "Aero Xanthates",    lbft: "112.5",    gcm: "1.8"),
        Material(name: "Aerolyte",    lbft: "51",    gcm: "0.82"),
        Material(name: "Aerosil, Fumed Silica",    lbft: "32",    gcm: "0.51"),
        Material(name: "Aerosil, Silicon Dioxide",    lbft: "30",    gcm: "0.48"),
        Material(name: "Alaluren",    lbft: "112",    gcm: "1.79")]

    var searchMaterial = [String]()
    var searching = false

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
    }
}

extension ViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searching {
            return searchMaterial.count
        } else {
            return materialData.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.numberOfLines = 0
        if searching {
            cell.textLabel?.text = searchMaterial[indexPath.row]
        } else {
            cell.textLabel?.text = materialData[indexPath.row] // <-- ERROR Cannot assign value of type 'Material' to type 'String'
        }
        return cell
    }

}

extension ViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchBar.setShowsCancelButton(true, animated: true)
        searchMaterial = materialData.filter({$0.prefix(searchText.count) == searchText}) // <-- ERROR Cannot assign value of type '[Material]' to type '[String]'
                                                                                          // <-- ERROR Value of type 'Material' has no member 'prefix'
        searching = true
        tableView.reloadData()

    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.setShowsCancelButton(false, animated: true)
        searching = false
        searchBar.text = ""
        tableView.reloadData()

    }

}



there is no没有

materialData[0] etc...

declare your array such as声明您的数组,例如

var searchMaterial:[String] = []

then you can access it like然后你可以像访问它

searchMaterial[indexPath.row]

1) cell.textLabel?.text = materialData[indexPath.row] the materialData[indexPath.row] will provide you with an object of type Material and not string. 1) cell.textLabel?.text = materialData[indexPath.row] materialData[indexPath.row] 将为您提供材料类型的 object,而不是字符串。 Not sure what value you are expecting.不确定您期望什么价值。 But changing it to但将其更改为

materialData[indexPath.row].name

2) searchMaterial = materialData.filter({$0.prefix(searchText.count) == searchText}) // <-- ERROR Cannot assign value of type '[Material]' to type '[String]' 2) searchMaterial = materialData.filter({$0.prefix(searchText.count) == searchText}) // <-- 错误不能将类型'[Material]'的值分配给类型'[String]'

changing to更改为

   var searchMaterial:[Material] = []
   searchMaterial = materialData.filter { $0.name.contains(searchText) }

Hi Sean I believe I have solved this,嗨,肖恩,我相信我已经解决了这个问题,

Everything in your tableView delegate functions are correct您的 tableView 委托函数中的所有内容都是正确的

Make sure to create this var at top level确保在顶层创建这个 var

var searchMaterial = [Material]() 

Then add this to your searchBar function:然后将此添加到您的 searchBar function:

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    guard !searchText.isEmpty else {
        searchMaterial = materialData
        tableView.reloadData()
        return // When no items are typed, load your array still 

    }
    searchMaterial = materialData.filter({ (Material) -> Bool in
        Material.title.lowercased().contains(searchText.lowercased())
 })
    searchBar.setShowsCancelButton(true, animated: true)
    searching = true
    tableView.reloadData()

Hope this helped!!!希望这有帮助!!!

do you want to search by name ?你想按name搜索吗? If so, you can fix the second ERROR like this:如果是这样,您可以像这样修复第二个ERROR

searchMaterial = materialData
    .map({ $0.name }) // convert to [String]
    .filter { $0.hasPrefix(searchText) } // search

The first one can be fixed like this:第一个可以像这样固定:

cell.textLabel?.text = materialData[indexPath.row].name

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

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