alias235
alias235

Reputation: 53

Search for multiple Properties with RealmSearchViewController

Overview: I am trying to get one search bar to search for different properties based on the input text. For example, if I have an address book with 'Names' and 'Numbers', I want a string on the search bar to search 'Names' and if an Int is entered in the search bar, to search 'Numbers'. (just like the iPhone's Phone app)

Steps taken:

1) I have implemented the RealmSearchViewController a la Realm's tutorial. (https://realm.io/news/building-an-ios-search-controller-in-swift/)

2) I have worked out how to assign the searchPropertyKeyPath property via initialisation. (see below if it helps anyone)

required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.searchPropertyKeyPath = "PhoneNumber" print("hello") print("Searchbar:", self.searchBar.text) }

Problem: I can't worked out how to a) scan searchbar.text [to check if it is int or string] and then b) modify the searchPropertyKeyPath [to search the appropriate property].

Any views on how to go about this?

(My guess would be to override and then modify the refreshSearchResults() func from the RealmSwiftViewController file. And yes, I have tried this, but ran into coding issues, which I didn't want to bring up in this question)

Upvotes: 0

Views: 857

Answers (3)

Jonathan Tuzman
Jonathan Tuzman

Reputation: 13308

My answer is sort of a workaround but it should work fine. You create a property that contains all the information you might want to search, then have that be the search property.

Let's assume your contacts are being created from a CSV and you've somehow gotten that CSV info into a struct. For simplicity's sake I'm leaving out any reference to the realm.

class Contact: Object {
    var name = ""
    var number = 0
    var fullInfo = ""
}

struct ContactInfo {
    var name: String
    var number: Int
}

func createContact(from info: ContactInfo) {
    var newContact = Contact() // your Object subclass
    newContact.name = info.name
    newContact.number = info.number
    newContact.fullInfo = "\(info.name) - \(String(info.number))"
}

Then you set your searchProperty to fullInfo.

Note that while it's tempting to make fullInfo a computed property, this won't work because you can't have a computed property for a searchProperty.

Upvotes: 0

alias235
alias235

Reputation: 53

Thank you to those who replied, my solution was to not use the RealmSearchViewController, and instead to use Realm's predicates with xcode's UISearchController a la this tutorial: https://www.raywenderlich.com/113772/uisearchcontroller-tutorial.

Upvotes: 0

jpsim
jpsim

Reputation: 14409

Realm uses NSPredicate for querying, and NSPredicate easily allows querying on multiple properties using NSCompoundPredicate:

class Person: Object {
  dynamic var name = "John"
  dynamic var phoneNumber = "1-800-DINOSAUR"
}
let searchString = "John"
let subpredicates = ["name", "phoneNumber"].map { property in
  NSPredicate(format: "%K CONTAINS %@", property, searchString)
}
let predicate = NSCompoundPredicate(orPredicateWithSubpredicates: subpredicates)
let johnInNameOrNumber = realm.objects(Person).filter(predicate)

To learn more about NSPredicate syntax, you should refer to Realm's NSPredicate Cheatsheet.

Upvotes: 5

Related Questions