Search code examples
swiftfilterrealmpredicate

RealmSwift + Multiple Predicate


I have no idea how to combine predicate based on user selection. Here is an overview of my data.

Person.swift

class Person: Object {

   let id = RealmOptional<Int>()
   dynamic var name = ""
   dynamic var console = ""

   override static func primaryKey() -> String {
      return "id"
}

sample json data

{
 "id": 822,
 "name": "Ron",
 "console": "XBox"
},
{
 "id": 823,
 "name": "Jenny"
 "console": "Playstation 4"
}

say for example i have alot of data and console consist of either "XBox", "Playstation 4", "Wii", "Sega" or "PS Vita". I create a checkbox filtering option to allow user to selected the option they want to filter and show the name of the person who owns which console.

For example if they select both "XBox" and "Playstation 4" how do i predicate them both and show the result of the person name? Currently i can only show one option like this.

var player: Results<Person>!

func filter(sender: AnyObject) {
    let realm = try! Realm()
    self.player = realm.objects(Person).filter("%K = %@", "console", "XBox")
}

Solution

  • You shouldn't dynamically craft an NSPredicate query string. It's much easier (and safer) to create an NSCompoundPredicate programmatically. You can pass NSPredicates to Realm's RealmCollectionType.filter(...) method. Here's an example to get all Persons who have either an Xbox or a Playstation 4:

    // could use .AndPredicateType here too, depending on what you want
    let query = NSCompoundPredicate(type: .OrPredicateType, subpredicates: [NSPredicate(format: "console = 'Xbox'"), NSPredicate(format: "console = 'Playstation 4')])
    let player = realm.objects(Person).filter(query)
    

    Although in your case, you might be better off using an IN query if you want OR semantics:

    let selectedConsoles = ["Xbox", "Playstation 4"]
    let player = realm.objects(Person).filter("console IN %@", selectedConsoles)