过滤数组并在表格视图中显示?

inf*_*ouk 3 uitableview uisearchbar swift

我想搜索名称键的练习字典,然后在表格视图中显示过滤结果.我正在使用这个功能

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    let filtered = exercises.filter { $0["name"] == searchText }
    print(filtered)

    if(filtered.count == 0){
        searchActive = false;
    } else {
        searchActive = true;
    }
    self.exercisesTableView.reloadData()
}
Run Code Online (Sandbox Code Playgroud)

变量:

var exercises = [Exercise]()
var filtered: [NSMutableArray] = []
var searchActive: Bool = false
Run Code Online (Sandbox Code Playgroud)

在搜索功能中,我收到错误

Type'Exercise'没有下标成员

然后我有一个问题,结果是一个NSMutableArray,所以我不能将结果名称设置为单元格文本来显示

无法将'NSMutableArray'类型的值转换为强制类型'String'

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    if (searchActive){
        cell.textLabel?.text = filtered[indexPath.row] as String
    } else {
        let exercise = exercises[indexPath.row]

        cell.textLabel!.text = exercise.name
    }
    return cell
}
Run Code Online (Sandbox Code Playgroud)

这是我的练习词典供参考:

final public class Exercise {
    var id: Int
    var descrip: String
    var name: String
    var muscles: [Int]
    var equipment: [Int]

    public init?(dictionary: [String: Any]) {

        guard
            let id = dictionary["id"] as? Int,
            let descrip = dictionary["description"] as? String,
            let name = dictionary["name"] as? String,
            let muscles = dictionary["muscles"] as? [Int],
            let equipment = dictionary["equipment"] as? [Int]

            else { return nil }

        self.id = id
        self.descrip = descrip
        self.name = name
        self.muscles = muscles
        self.equipment = equipment

    }
Run Code Online (Sandbox Code Playgroud)

我可以通过使var过滤来修复第二个错误:[String] = []所以它可以用作单元格标题,但这并不能解决第一个错误,我不确定是不是正确的方法呢?

Nir*_*v D 6

你的filtered类型[Exercise]也需要过滤它.

var filtered = [Exercise]() 

self.filtered = exercises.filter { $0.name == searchText }
Run Code Online (Sandbox Code Playgroud)

$0Exercise对象的类型,因此您需要使用它来访问其属性名称$0.name.

编辑:如果你想要只有名字的filtered类型,[String]那么你可能需要使用两者map并且filter像这样.

self.filtered = exercises.filter { $0.name == searchText }.map { $0.name }
Run Code Online (Sandbox Code Playgroud)

要么

self.filtered = exercises.map { $0.name }.filter { $0 == searchText }
Run Code Online (Sandbox Code Playgroud)

或者直接使用filterMap@dfri建议.

self.filtered = exercises.flatMap{ $0.name == searchText ? $0.name : nil }
Run Code Online (Sandbox Code Playgroud)


vad*_*ian 5

我昨天告诉过你在使用自定义类时忘记字典语义
不要使用键下标!

正如其他答案中提到的,您还必须声明filtered[Exercise]

var filtered = [Exercise]() 
Run Code Online (Sandbox Code Playgroud)

和过滤器

self.filtered = exercises.filter { $0.name == searchText }
Run Code Online (Sandbox Code Playgroud)

但是,如果您还想搜索部分字符串,请使用

self.filtered = exercises.filter {$0.name.range(of: searchText, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil }
Run Code Online (Sandbox Code Playgroud)

因为过滤和未过滤的数组都是[Exercise]你必须以cellForRowAtIndexPath这种方式改变的类型

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    let exercise : Exercise 
    if (searchActive){
        exercise = filtered[indexPath.row]
    } else {
        exercise = exercises[indexPath.row]
    }
    cell.textLabel!.text = exercise.name
    return cell
}
Run Code Online (Sandbox Code Playgroud)