过滤数组并在表格视图中显示?
Posted
技术标签:
【中文标题】过滤数组并在表格视图中显示?【英文标题】:Filtering Array and displaying in Table View? 【发布时间】:2016-11-14 12:02:11 【问题描述】:我想在练习字典中搜索名称键,然后在表格视图中显示过滤后的结果。我正在使用这个功能
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 filters: [String] = [] 来修复第二个错误,这样它就可以用作单元格标题,但这并不能解决第一个错误,而且我不确定这样做是否正确?
【问题讨论】:
【参考方案1】:您的filtered
也是[Exercise]
的类型,您需要对其进行过滤。
var filtered = [Exercise]()
self.filtered = exercises.filter $0.name == searchText
这里$0
是Exercise
对象的类型,因此您需要使用$0.name
访问其属性名称。
编辑:如果您希望filtered
是只有名称的[String]
类型,那么您可以像这样同时使用map
和filter
。
self.filtered = exercises.filter $0.name == searchText .map $0.name
或
self.filtered = exercises.map $0.name .filter $0 == searchText
或者按照@dfri 的建议直接使用filterMap
。
self.filtered = exercises.flatMap $0.name == searchText ? $0.name : nil
【讨论】:
谢谢你,但是如果我将过滤设置为也 = [Exercise]() 当它不再是字符串时,我如何将它映射到单元格名称?看到我的代码部分 cell.textLabel?.text = filters[indexPath.row] as String 我试过了,但它不喜欢它,我需要编辑变量还是只插入规定的代码?错误是无法将“String”类型的值转换为闭包结果类型“Exercise”,并且在表格单元格名称语句中:无法将“Exercise”类型的值转换为强制类型“String” @NiravD 请注意,使用链式filter
和 map
操作的常见替代方法是单个 flatMap
操作:self.filtered = exercises.flatMap $0.name == searchText ? $0.name : nil
。
@infernouk 是的,现在您需要将filtered
更改为[String]
已正确写入Edit
行检查。
感谢我删除了控制器并制作了插座!【参考方案2】:
我昨天告诉过你忘记字典语义时使用自定义类。 不要使用键下标!
正如其他答案中提到的,您必须将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
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
【讨论】:
谢谢我试过了,因为保持过滤器类型相同似乎更干净,没有错误只是我在 Nirav 的响应 cmets 中提到的在搜索栏中输入字母时仍然遇到这种奇怪的崩溃 你在使用UISearchController
吗?如果是,请使用 searchResultController.isActive
检查搜索状态,而不是自定义布尔变量。
所以我需要将 searchResultController 声明为变量?只是将其换成 searchResultController.isActive 会导致未解决的标识符错误。我现在让 searchController = UISearchController(searchResultsController: nil)
是的,当然var searchResultController: UISearchController!
但是你也应该使用updateSearchResults(for
而不是textDidChange
我已经更新到 searchResultController.isActive 但是现在这会导致致命的崩溃,只是在输入之前单击搜索字段。要更改为 updateSearchResults,它如何适合 textDidChange 语句? func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)【参考方案3】:
这里的问题是$0["name"] == searchText
。 $0
在这种情况下属于 Excersise
类型,您将其称为数组。此行应如下所示:
let filtered = exercises.filter $0.name == searchText
【讨论】:
【参考方案4】:就我而言,我在一些个人项目中使用了以下代码,代码与之前的答案非常相似。我只使用contains
。
func filter(query: String)
if query.isEmpty
self.filteredData = self.originalData
else
self.filteredData = self.originalData.filter
$0.prop1!.lowercased().contains(query)
【讨论】:
【参考方案5】:清洁有效的方法
在你的类中声明这些数组:
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]
【讨论】:
以上是关于过滤数组并在表格视图中显示?的主要内容,如果未能解决你的问题,请参考以下文章
Swift UITableView(无部分)过滤到带有部分的表格视图
单击过滤器选项时,帖子/图像重叠,并在窗口调整大小后显示在砖石视图中