Filtering dictionary In Swift - ios

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)

Related

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

Link arrays for UISearchController in Swift

I m using a UISearchController to let the user search though my data (these comes from XML and been parsed to arrays), now i want to add more then one UILabel into my Cell, but these UILabel Information comes from different arrays.
As soon as i update my Search, the 2. array does not get sorted the same way like the first does.
AP = ["FIRST1","FIRST2","FIRST3","FIRST4","FIRST5"]
APSecound = ["SEC1","SEC2","SEC3","SEC4","SEC5"]
var filteredTableDataAP = [String]()
var filteredTableDataAPSecound = [String]()
func updateSearchResultsForSearchController(searchController: UISearchController)
{
filteredTableDataIcao.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (AP as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredTableDataAP = array as! [String]
//i think here i some how could set index of "filteredTableDataAP = filteredTableDataAPSecound" so they been filtered like the same shema
self.tableView.reloadData()
}
Override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCellSearch", forIndexPath: indexPath) as! CustomTableViewCellSearch
if (self.resultSearchController.active) {
cell.APLB.text = filteredTableDataAP[indexPath.row]
cell.APSecoundLB.text = filteredTableDataAPSecound[indexPath.row]
return cell
}
else {
cell.APLB.text = AP[indexPath.row]
cell.APSecoundLB.text = APSecound[indexPath.row]
return cell
}
}
On first run without searching the cell looks fine like
(FIRST1)(SEC1)
(FIRST2)(SEC2)
(FIRST3)(SEC3)
(FIRST4)(SEC4)
But once i search for "4" the cell looks like
(FIRST4)(SEC1)
is there any easy way to "keep the position of the second array like the one of the first"
The way i have used is below
you have two array :
AP = ["FIRST1","FIRST2","FIRST3","FIRST4","FIRST5"]
APSecound = ["SEC1","SEC2","SEC3","SEC4","SEC5"]
var getIndex = 0
if (self.SearchController.active) // check if SearchController isactive
{
//This will get the index of main array
getIndex = AP.indexOf(filteredsearchPost[indexPath.row])!
//According to example index should be 1 for "FIRST2"
. cell.APSecoundLB.text = APSecound[getIndex]
//set it with the retrived index and its done
//it will print "SEC2"
}else {
getIndex = indexPath.row
cell.APLB.text = AP[getIndex]
cell.APSecoundLB.text = APSecound[getIndex]
//Do the else part here
}
you just filtered the AP not filtered APSecound
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (AP as NSArray).filteredArrayUsingPredicate(searchPredicate)
let arraySecond = (APSecound as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredTableDataAP = array as! [String]
filteredTableDataAPSecound = arraySecond as! [String]
or you can use filteredResault: [[String: String?]] , [String: String?] is the Dictionary, filteredResault is Dictionary array. dict like ["AP": "FIRST1", "APSecound": "SEC1"]

How to search inside of Dictionary in Swift

In my UITableView I have cells with avatar image and name surname(UIImage and Label). And I want to search inside of my UITableView. So, when I type my user's name or surname it would show user's name surname with the avatar image.
Now, I can search just inside of an array with the next code:
var rosters = [String: UIImage]()
var displayNames = [String]()
var filteredTableData = [String]()
// Here I remove all elements from the array and add to it user display name and avatar
rosters.removeAll(keepCapacity: false)
for user in OneRoster.buddyList.fetchedObjects! {
var roster = OneRoster.userFromRosterForJID(jid: user.jidStr)
var image = OneChat.sharedInstance.xmppvCardAvatarModule?.photoDataForJID(roster?.jid)
rosters[user.displayName] = UIImage(data: image!)!
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> onlineUserCell {
let cell:onlineUserCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! onlineUserCell
if (self.resultSearchController.active) {
cell.username.text = filteredTableData[indexPath.row]
//cell.avatarImage.image = images[indexPath.row]
return cell
}
}
func updateSearchResultsForSearchController(searchController: UISearchController)
{
filteredTableData.removeAll(keepCapacity: false)
displayNames.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
for (name, image) in rosters {
displayNames.append(name)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (displayNames as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredTableData = array as! [String]
}
let array = (displayNames as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredTableData = array as! [String]
self.tableView.reloadData()
}
So, this code searches just among name surname, without avatar image. I thought, that I can use dictionary, as:
var users = [UIImage: String]()
and later search by String and show as UIImage and String together in the cell. But I searched a lot and couldn't found how to search, that later I can search by String and to get result with UIImage, too.
Any ideas?
Searching the dictionary could be done by just accessing the values from the dictionary and searching them like
var users = [UIImage: String]()
let values = Array(users.values)
However this use of dictionary seems a bit wrong as you will never look up a value based on the UIImage I guess.
What you should use instead then would be a tuple or a class that holds both UIImage and String
var users = [(image:UIImage,name:String)]()
you can then simply filter the values like
users.filter { (element:(image:UIImage, name:String)) -> Bool in
return element.name.containsString(searchfrase)
}

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.

UISearchController searching two arrays

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

Resources