Search code examples
iosswiftuisearchcontroller

How to search through array properties in Model


I have to make a Contacts-like app. I have a model object. Please notice the 2 properties phoneNumbers & addresses are Arrays

class Contact: NSObject {

var name: String?
var companyName: String?
var phoneNumbers: [String]?
var addresses: [String]?

.. // Custom init methods etc

}

Now I have to populate these and search them using search View Controller.

I followed the simple way, implemented a searchViewController in TableViewController. Much like here: https://www.raywenderlich.com/113772/uisearchcontroller-tutorial

func filterContentForSearchText(searchText: String, scope: String = "All") {
    filteredContacts.removeAll(keepCapacity: false)

    let searchPredicate = NSPredicate(format: "name CONTAINS[c] %@ OR companyName CONTAINS[c] %@", searchController.searchBar.text!, searchController.searchBar.text!, searchController.searchBar.text!)

    let array = (contacts as NSArray).filteredArrayUsingPredicate(searchPredicate)
    filteredContacts = array as! [Contact]

    tableView.reloadData()
}

My problem is how to search throught the array of phone numbers and addresses? The above code works good searching through non-array properties, but how to search through the arrays?


Solution

  • Here is code you paste in a playground to test searching within properties that are arrays. I kept the search functions simple for clarity, but the code can be shortened using filters and closures.

    import UIKit
    
    class Contact  {
    
          var name: String?
          var companyName: String?
          var phoneNumbers: [String]?
          var addresses: [String]?
    
          init (name: String, companyName: String, phoneNumbers: [String], addresses: [String]) {
                self.name = name
                self.companyName = companyName
                self.phoneNumbers = phoneNumbers
                self.addresses = addresses
          }
    }
    
    var contacts: [Contact] =
          [(Contact.init(name: "Tom Jones", companyName: "Jones", phoneNumbers: ["111-1111", "111-1112", "111-1113"], addresses: ["Hollywood", "New York"])),
           (Contact.init(name: "Aretha Franklin", companyName: "Franklin", phoneNumbers: ["111-1114", "111-1115", "111-1116"], addresses: ["Detroit", "Hollywood"])),
           (Contact.init(name: "Axel Rose", companyName: "Rose", phoneNumbers: ["111-1117", "111-11128", "111-1111"], addresses: ["London", "New York"])) ]
    
    let phoneNumberSearchString = "111-1111"
    
    func searchByPhoneNumber (searchNumber: String, inDataSet contacts: [Contact]) -> [Contact] {
          var searchResult: [Contact] = []
          for contact in contacts {
                for phoneNumber in contact.phoneNumbers! {
                      if phoneNumber == searchNumber {
                            searchResult.append(contact)
                      }
                }
          }
          return searchResult
    }
    
    func searchByAddress (searchAddress: String, inDataSet contacts: [Contact]) -> [Contact] {
          var searchResult: [Contact] = []
          for contact in contacts {
                for address in contact.addresses! {
                      if address == searchAddress {
                            searchResult.append(contact)
                      }
                }
          }
          return searchResult
    }
    
    let foundContacts = searchByPhoneNumber("111-1111", inDataSet: contacts)
    
    for contact in foundContacts {
          print(contact.name!)
    }
    
    let foundContacts2 = searchByAddress("Hollywood", inDataSet: contacts)
    
    for contact in foundContacts2 {
          print(contact.name!)
    }
    
    /* Print results
    
     Tom Jones
     Axel Rose
     Tom Jones
     Aretha Franklin
    
     */