Searching string in NSArray of custom object using NSPredicate - ios

I have two classes like below:
class City : NSObject{
var header:String? = nil
var areas:NSMutableArray? = nil //Contain array of Area
//Return array of City objects
class func generate(cityCount:NSInteger) -> NSMutableArray{...}
}
and
class Area : NSObject{
var title:String? = nil
var address:String? = nil
}
//Return array of Area objects
class func generate(areaCount:NSInteger) -> NSMutableArray {...}
Now, I have Array of City like this declared in my viewcontroller:
var cities = City.generate(200)
and when I search the header inside using NSPredicate it work perfectly
let pred = NSPredicate(format: "SELF.header CONTAINS %#",searchString)
let filteredCities = self.cities.filteredArrayUsingPredicate(pred)
But when I search the cities->areas->address (I want to search address). It is not working. It is always return 0 object. Here what I am trying:
let pred = NSPredicate(format: "SELF.areas.address CONTAINS %#",searchString) //name
let filteredCities = (self.cities as NSArray).filteredArrayUsingPredicate(pred)
EDIT
I need only the area object that contain matching address.
I have tried:
let pred = NSPredicate(format: "ANY areas.address CONTAINS %#",searchString)
This is giving the City object with all area object.
Thanks in advance.

Have try like this
let pred = NSPredicate(format: "ANY areas.address CONTAINS %#",searchString)

Try this bro,
let pred = NSPredicate(format: "SELF contains[c] %#",searchString)
let filteredCities = self.area.filteredArrayUsingPredicate(pred)

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

Search data in DB with CoreData and swift

I'm a new in swift and CoreData and I have a problem:
I have DB with 2 columns: "name" and "number", for example
name number
Bob 2
Helena 5
Helga 1
Matilda 0
I connect my UITableViewController with DB across CoreData and it's working (i see all DB in my simulator of iphone)
I want find with swift in my DB cells of column "number" with value, for example, "1" and "2" and show proper cell from column "name" and as result I want to see:
Bob 2
Helga 1
How better to do it? I tried to work with NSPredicate, but I don't understand how it works and how to do so that it will be worked.
Thanks!
Hi Add below function in your NSManagedObject extension
1) fetch data from coredata by id using predict
class func Search(PredictName:String, Uid:String, entityDescription: String,managedObjectContext: NSManagedObjectContext = appDelegate.managedObjectContext) -> [AnyObject]?
{
var ar:[AnyObject] = []
do
{
let predicate = NSPredicate(format: "\(PredictName) == %#", Uid)
let request = NSFetchRequest(entityName: entityDescription)
request.predicate = predicate
let result = try managedObjectContext.executeFetchRequest(request)
ar = result
}
catch(_)
{
ar = []
}
return ar as [AnyObject]
}
Function Call :
var lists:[ModelClassName]? = AdvertisementDataList.findByTypeInContext("user_id", url: self.Uid, entityDescription: "CoredataEntityName") as? [AdvertisementDataList]
It will return you predict column name data by row id
2) fetch all the data from coredata
class func Search(PredictName:String, entityDescription: String,managedObjectContext: NSManagedObjectContext = appDelegate.managedObjectContext) -> [AnyObject]?
{
var ar:[AnyObject] = []
do
{
let predicate = NSPredicate(format: "\(PredictName)")
let request = NSFetchRequest(entityName: entityDescription)
request.predicate = predicate
let result = try managedObjectContext.executeFetchRequest(request)
ar = result
}
catch(_)
{
ar = []
}
return ar as [AnyObject]
}
Function Call :
var lists:[ModelClassName]? = AdvertisementDataList.findByTypeInContext("user_id", entityDescription: "CoredataEntityName") as? [AdvertisementDataList]
It will return all the data by predict name.

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.

Swift Array of objects filtering

I've the following array of objects which I'm trying to filter and return for a searchDosplayController.
var family = [Family]()// fetchedFamily
var filteredFamily: [Family]! // filter fetched events
And that is how, I'm filtering it:
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchText = searchController.searchBar.text
self.filteredProvince = provinces
if !searchText.isEmpty {
let searchPredicate = NSPredicate(format: "name CONTAINS[c] %#", searchText)
let array = (filteredProvince as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredProvince = array as! [Province]
}
However nothing is getting returned when I'm searching. And I tried to do it in this way:
filteredFamily = searchText.isEmpty ? family : family.filter({(dataString: String) -> Bool in
return dataString.rangeOfString(searchText, options: .CaseInsensitiveSearch) != nil
})
But, I'm receiving the following error: 'Family is not a subtype of String'. Is there any better way to filter the Family? Because, the filtered result has to be sent back to searchDisplayController.
Thanks in advance.
So we have a Family class that does look like this right?
class Family {
let name : String
init(name:String) {
self.name = name
}
}
Then we have a list of families:
var families = [Family]()
And we want to extract all the families where the name property contains a given text.
let searchText = "something here"
Good, first of all we add this extension to the String struct.
extension String {
func contains(find: String) -> Bool {
return self.rangeOfString(find) != nil
}
}
And finally we can filter the families writing:
let filtered = families.filter { $0.name.contains(searchText) }
Hope this helps.

Resources