Reputation: 423
I have implemented code for searchBar
and it works if I either search the first or the last name of a person. For example, if I want to search Kate Bell, the search works if I write "Kate", and it works if I write "Bell". But if I write "Kate B" the search result disappear.
Here's my code:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.count == 0 {
isFiltered = false
tableViewOutlet.reloadData()
}else {
isFiltered = true
searchInternalArray = contactsInternalArray.filter({ object -> Bool in
guard let text = searchBar.text else {return false}
return object.firstName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)) || object.lastName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines))
})
searchArrayGroups = sectionsArrayGroups.filter({ object -> Bool in
guard let text = searchBar.text else {return false}
return object.firstName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)) || object.lastName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines))
})
searchArraySAEs = sectionsArraySAEs.filter ({ object -> Bool in
guard let text = searchBar.text else {return false}
return object.firstName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)) || object.lastName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines))
})
tableView.reloadData()
}
I fond this on SO
How to search by both first name and last name
It's in objective-c
and I have trouble implementing it into my own code. I tried something like this:
searchInternalArray = contactsInternalArray.filter({ object -> Bool in
guard let text = searchBar.text?.range(of: object.firstName + object.lastName) else {return false}
return object.firstName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)) || object.lastName.lowercased().contains(text.lowercased().trimmingCharacters(in: .whitespacesAndNewlines))
})
That's obviously not how it should be implemented though.
Edit
Didn't think it was relevant, but perhaps it is: I'm filtering multiple arrays
since I have data coming from three different sources to the tableView
. The whole searchBar
code looks like above. It's updated.
Upvotes: 0
Views: 699
Reputation: 1679
I got idea from flanker's answer.
This works for me
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.searchBar.showsCancelButton = true
if searchText != ""{
self.isSearchActive = true
if self.object.count != 0{
filteredContacts = self. object.filter(){
//("\(($0 as FetchedContact).firstName.lowercased()) \(($0 as FetchedContact).object.lowercased()) \(($0 as FetchedContact).telephone.lowercased())")
let name = ("\(($0 as ContactModel).firstName.lowercased()) \(($0 as ContactModel).lastName.lowercased()) \(($0 as ContactModel).mobileNumber.lowercased())")
return name.contains(searchText.lowercased())
}
}
self.tblContactList.reloadData()
}
}
Upvotes: 0
Reputation: 4200
Unless I'm missing something, there's a far simpler solution to this:
let name = firstname.lowercased() + " " + lastname.lowercased()
return name.contains(text.lowercased())
This works for any part of forename, surname, or the a part of the two with a space between. You should probably still trim leading/trailing spaces, and if you wanted to get rid of issues with variable spaces between the first and last names you could search/replace them double spaces with a single space.
Upvotes: 2
Reputation: 19750
Why not just create the full name from the two parts and search based on that.
let searchResults = contactsInternalArray.filter { object in
"\(object.firstName) \(object.lastName)".contains(searchText)
}
You can still lowercase them and trim if you want to.
Upvotes: 1