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

时间:2016-11-14 12:02:12

标签: swift uitableview uisearchbar

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

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()
}

变量:

var exercises = [Exercise]()
var filtered: [NSMutableArray] = []
var searchActive: Bool = false

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

  

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
}

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

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

    }

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

5 个答案:

答案 0 :(得分:6)

您的filtered也是[Exercise]类型,您需要过滤它。

var filtered = [Exercise]() 

self.filtered = exercises.filter { $0.name == searchText }

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

修改:如果您希望filtered仅包含[String]类型的名称,那么您可能需要同时使用mapfilter

self.filtered = exercises.filter { $0.name == searchText }.map { $0.name }

OR

self.filtered = exercises.map { $0.name }.filter { $0 == searchText }

或者直接使用filterMap作为@dfri建议。

self.filtered = exercises.flatMap{ $0.name == searchText ? $0.name : nil }

答案 1 :(得分:3)

我在昨天告诉你在使用自定义类时忘记了词典语义 不要使用密钥下载!

如其他答案中所述,您必须将var observableModule = require("data/observable") var ObservableArray = require("data/observable-array").ObservableArray; var arrNoticias = require('./home-view-model.js'); console.log(arrNoticias.getItem(0).titulo); 也声明为filtered

[Exercise]

并过滤

var filtered = [Exercise]() 

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

self.filtered = exercises.filter { $0.name == searchText }

<强>但是

由于过滤和未过滤的数组都是self.filtered = exercises.filter {$0.name.range(of: searchText, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil } 类型,您必须以这种方式更改[Exercise]

cellForRowAtIndexPath

答案 2 :(得分:0)

此处的问题是https://localhost:8243/authorize https://localhost:8243/token 。在此上下文中,$0["name"] == searchText属于$0类型,您可以将其称为数组。这一行应如下所示:

Excersise

答案 3 :(得分:0)

就我而言,我在某些个人项目中使用了以下代码,该代码与先前的答案非常相似。我只使用contains

func filter(query: String){
        if query.isEmpty {
            self.filteredData = self.originalData
        } else {
            self.filteredData = self.originalData.filter {
                $0.prop1!.lowercased().contains(query)
            }
        }
    }

答案 4 :(得分:0)

清洁有效的方法

在您的课程中声明以下数组:

var filteredData: [Exercise] = []  
{
    didSet
    { 
        tableView.reloadData()
    }
}

// once we get our data, we will put it into filtered array
// user will interact only with filtered array
var source: [Exercise] = [] 
{
    didSet
    { 
        filteredData = source
    }
}

实现以下功能:

extension ViewController: UISearchBarDelegate
{
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
    {        
        let searchText = searchText.lowercased()
        let filtered = source.filter({ $0.lowercased().contains(searchText) })
        filteredData = filtered.isEmpty ? source : filtered
    }
}

您会注意到,用户永远不会与原始数组进行交互,而只会与过滤后的数组进行交互。

// MARK: UITableViewDataSource

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

// MARK: UITableViewDelegate

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

    cell.textLabel?.text = filteredData[indexPath.row]
}