UISearchController searching two arrays - ios

How can I use UISearchController to search two different arrays and create two new filtered arrays based on that search? The parameters should only require that one array contain the string, then if one of the arrays have it, both indexes should be added. As of now, I use
func updateSearchResultsForSearchController(searchController: UISearchController)
{
filteredKeys.removeAll(keepCapacity: false)
filteredValues.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text)
let array = (values as NSArray).filteredArrayUsingPredicate(searchPredicate)
println(array)
let arrayTwo = (keys as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredKeys = arrayTwo as! [String]
filteredValues = array as! [String]
self.tableView.reloadData()
}
However, this is very bad and often crashes the app due to a difference in the count of the filtered arrays. Please help, I have been stuck on this for a while.
The search should look at the content:
arrayOne = ["title1", "title2", "title3]
arrayTwo = ["message1", "message2", "message3]
and should filter the arrays based on the search title1 as
arrayOneFiltered = ["title1"]
arrayTwo = ["message1"]
Could someone help me with the predicate string and the filtering please?
Again, this is using a UISearchController in a TableViewController

Since Dictionary or NSDictionary already provides key-value pair type mechanism, you can wrap your related values in a dictionary like this:
var dictionary = ["title_key": "title something", "message_key": "message text"]
And then you can make an array of dictionaries.
var masterArrayOfDictionaries = [ dictionary , ["title_key": "title something 2", "message_key": "message text 2"]]
You can make dictionary at runtime and append to array:
var dictionary3 = ["title_key": "title something 3", "message_key": "message text 3"]
masterArrayOfDictionaries.append(dictionary3)
Now your predicate should look like:
//You want to search on the 'message_key' so put it in the predicate
let searchPredicate = NSPredicate(format: "message_key CONTAINS[c] %#", searchController.searchBar.text)
Now apply the predicate as follow:
let arrayFiltered = (masterArrayOfDictionaries as NSArray).filteredArrayUsingPredicate(searchPredicate)
This will give you filtered array having the dictionaries that contains searched text against their message_key

Related

Filter with NSPredicate on custom object in Swift 3+ [duplicate]

This question already has an answer here:
Filter array of custom objects in Swift
(1 answer)
Closed 4 years ago.
I want to filter on my custom object. My custom object look
class Requestlist: NSObject, NSCoding {
let artist: String
let title: String
let id: String
let type: String
init(artist: String, title: String, id: String, type: String) {
self.artist = artist
self.title = title
self.id = id
self.type = type
}
}
But the program keeps crashing with this code:
let textInput = txbSearch.text
let pred = NSPredicate(format: "ANY artist contains[c] %# OR title contains[c] %#",textInput!)
let filteredArray = (Constants.liveRequestlist as NSArray).filtered(using: pred)
print(filteredArray)
The code runs on KeyboardChange and must be updated when the keyboard input change like a live search. I also want to search on a part of an artist or title. (Like the SQL Like operator)
Two issues:
Any is only for key paths or to-many relationships.
The second parameter (representing the second %#) is missing.
let pred = NSPredicate(format: "artist contains[c] %# OR title contains[c] %#",textInput!, textInput!)
It's highly recommended to use the native Swift filter API:
let filteredArray = Constants.liveRequestlist.filter{ $0.artist.range(of: textInput!, options: [.caseInsensitive]) != nil
|| $0.title.range(of: textInput!, options: [.caseInsensitive]) != nil }

How to declare an Array of Realm Results in Swift 4?

Is it possible to make an array of realm results in swift 4? , I've tried this one var RealmArray = [[Results<Object1>?](),[Results<Object2>?](),[Results<Object3>?](),[Results<Object4>?]()] as [Any] but this looks like not good to me , I want to use and display the data inside of every object to the tableView but I don't know how to properly use their indices. Someone knows how to declare an Array of Realm Results?
Or Do you know how to merge the 4 Realm Results?
This is for my SearchBar(For those who want to know for what I will use this for).
my declaration
var main_tcb_filteredArray:Results<TrialCourtBranches>?
var main_ibp_filteredArray:Results<IBPChapters>?
var main_pao_filteredArray:Results<Pao>?
var main_lac_filteredArray:Results<LegalAidClinics>?
var RealmArray = [[Results<TrialCourtBranches>?](),[Results<IBPChapters>?](),[Results<Pao>?](),[Results<LegalAidClinics>?]()] as [Any]
Filtering for my searchbar
let tcb = realm.objects(TrialCourtBranches.self)
let tcb_predicate = NSPredicate(format: "(branch_name CONTAINS[c] %#)",searchText.lowercased())
main_tcb_filteredArray = tcb.filter(tcb_predicate)
let ibp_predicate = NSPredicate(format: "(chapter CONTAINS[c] %#)",searchText.lowercased())
let ibp = realm.objects(IBPChapters.self)
main_ibp_filteredArray = ibp.filter(ibp_predicate)
let pao_predicate = NSPredicate(format: "office_name CONTAINS[c] %#",data.lowercased())
let pao = realm.objects(Pao.self)
main_pao_filteredArray = pao.filter(pao_predicate)
let lac_predicate = NSPredicate(format: "school CONTAINS[c] %#",data.lowercased())
let lac = realm.objects(LegalAidClinics.self)
main_lac_filteredArray = lac.filter(lac_predicate)
main_combined_filteredArray = [main_tcb_filteredArray!,main_ibp_filteredArray!,main_pao_filteredArray!,main_lac_filteredArray!]
self.tableView.reloadData()

Filtering dictionary In Swift

hello I am am new in Swift and trying to implement a search bar on table view. so I followed one tutorial on Youtube and implement the tutorial correctly. But I have some problems working with my data. As in tutorial the data was in NSArray and mine is coming from web service and its in NSDictionary
So My data is saved in NSDictionary and If I have to access the variables I do this
cell.countryNameLabel.text = (((dict["\(indexPath.item)"] as?NSDictionary)!["Countries"] as?NSDictionary)!["name"] as?NSString)! as String
okay In tutorial He has done something like this
var filterTableData = [String]()
var tableData = ["one","two","three"]
func updateSearchResultsForSearchController(searchController: UISearchController) {
filterTableData.removeAll(keepCapacity: false)
let searchPredict = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (tableData as NSArray).filteredArrayUsingPredicate(searchPredict)
filterTableData = array as! [String]
self.tableView.reloadData()
}
and Now I want to know how can I implement this as I have data stored in NSdictionary and variable is dict
You can store the keys of the dictionary to an Array object
and use it in the function.
var filterTableData = [String]()
var tableData = Array(dict.keys)

Filter by array of Objects searchController

I have created an searchController and therefor i'm trying t make it filter content according to the text in the UISearchController. I've created a custom Object looking like below. I've tried using NSPredicate, but keep getting:
cannot convert value of type NSPredicate to expected type #noescape (organization) throws...
class Organization: Object {
var id: Int = 0
var name: String = ""
var shortName: String = ""
var image: NSData = NSData()
var pinImage: NSData = NSData()
let locations = List<Location>()
}
Then I have an array called sortedLocations in my ViewController which contains a number of Organization Objects.
What I've tried so far:
func updateSearchResultsForSearchController(searchController: UISearchController)
{
filteredTableData.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF.name CONTAINS[c] %#", searchController.searchBar.text!)
let array = sortedLocations.filter(searchPredicate)
filteredTableData = array as! [Organization]
self.tableView.reloadData()
}
The filter() method of SequenceType does not take an NSPredicate
as an argument, but a closure, e.g.
let filteredTableData = sortedLocations.filter {
$0.name.localizedCaseInsensitiveContainsString(searchText)
}
The closure is called for each array element (here using the shorthand
argument $0) and returns true or false to indicate if the element
is to be included in the filtered result or not.
You can use an NSPredicate to filter an NSArray, that would look
like
let filtered = someNSArray.filteredArrayUsingPredicate(predicate)
but there is no reason to use this if you have a Swift array.

Searching by object property with UISearchController?

In my updateSearchResultsForSearchController method, I have a searchPredicate that I use to find matches, however, I want to learn how to use it with an Object's property.
I have an object called Product that has a String property called title which I would like to use as my search parameter. So far, this is what my search function looks like:
func updateSearchResultsForSearchController(searchController: UISearchController) {
productSearchResults.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text)
let array = (orderGuideItemsList as NSArray).filteredArrayUsingPredicate(searchPredicate)
productSearchResults = array as! [Product]
self.tableView.reloadData()
}
where orderGuideItemsList is an array of Product objects
So is there a way for me to search based on Proudct's title property? It doesn't have to use a predicate but that's what I have from a previous tutorial.
Thanks!
You can update your predicate to
let searchPredicate = NSPredicate(format: "SELF.title CONTAINS[c] %#", searchController.searchBar.text)
This should work fine.

Resources