问题
I want to search an dictionary of exercises for the name key and then show the filtered result in the table view. I am using this function
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()
}
Variables:
var exercises = [Exercise]()
var filtered: [NSMutableArray] = []
var searchActive: Bool = false
In the search function I get the error
Type'Exercise' has no subscript members
and then i have the issue that the result is an NSMutableArray and so I cant set the result names as cell text to display
Cannot convert value of type 'NSMutableArray' to type 'String' in coercion
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
}
Here is my Exercise dictionary for reference:
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
}
I can fix the second error by making var filtered: [String] = [] so it can be used as a cell title, but that doesnt resolve the first error and im not sure is the right way to go about it?
回答1:
Your filtered
also type of [Exercise]
and you need to filter it like.
var filtered = [Exercise]()
self.filtered = exercises.filter { $0.name == searchText }
Here $0
is type of Exercise
object, so you need to access its property name using $0.name
.
Edit: If you want filtered
as type of [String]
with only name then you can need to use both map
and filter
like this.
self.filtered = exercises.filter { $0.name == searchText }.map { $0.name }
OR
self.filtered = exercises.map { $0.name }.filter { $0 == searchText }
OR directly using filterMap
as @dfri suggested.
self.filtered = exercises.flatMap{ $0.name == searchText ? $0.name : nil }
回答2:
I told you yesterday forget the dictionary semantics when using a custom class.
Do not use key subscripting!
As mentioned in the other answers you have to declare filtered
also as [Exercise]
var filtered = [Exercise]()
and filter
self.filtered = exercises.filter { $0.name == searchText }
However if you want to search also for partial strings use
self.filtered = exercises.filter {$0.name.range(of: searchText, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil }
But
since both filtered and unfiltered arrays are of type [Exercise]
you have to change cellForRowAtIndexPath
this way
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
}
回答3:
The issue here is $0["name"] == searchText
. $0
in this context is of Excersise
type and you refer to it as it's an array. This line should look like this:
let filtered = exercises.filter { $0.name == searchText }
回答4:
In my case I have used the following code in some personal projects, the code is very similar to the previous answers. I just use contains
.
func filter(query: String){
if query.isEmpty {
self.filteredData = self.originalData
} else {
self.filteredData = self.originalData.filter {
$0.prop1!.lowercased().contains(query)
}
}
}
来源:https://stackoverflow.com/questions/40588332/filtering-array-and-displaying-in-table-view