What i should change in my code to access all the contacts instead of just 1 contact with swift?

253 Views Asked by At

I have a really specific problem. I want to access and present to a table view the user's contact list. The problem is that when I run the code I access only one contact from the contact list. I'm trying to think what I should change but nothing so far. Given the code below what I need to change the achieve the result that I want? Here is the code:

import UIKit
import Contacts
import AddressBook

 class MasterViewController: UITableViewController {

var detailViewController: DetailViewController? = nil
var objects = [CNContact]()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let addExisting = UIBarButtonItem(title: "Add Existing", style: .Plain, target: self, action: #selector(MasterViewController.addExistingContact))
    self.navigationItem.leftBarButtonItem = addExisting

    if let split = self.splitViewController {
        let controllers = split.viewControllers
        self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
    }

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MasterViewController.insertNewObject(_:)), name: "addNewContact", object: nil)
    self.getContacts()
}

func getContacts() {
  let store = CNContactStore()

  if CNContactStore.authorizationStatusForEntityType(.Contacts) == .NotDetermined {
    store.requestAccessForEntityType(.Contacts, completionHandler: { (authorized: Bool, error: NSError?) -> Void in
      if authorized {
        self.retrieveContactsWithStore(store)
      }
    })
  } else if CNContactStore.authorizationStatusForEntityType(.Contacts) == .Authorized {
    self.retrieveContactsWithStore(store)
  }

}

 func retrieveContactsWithStore(store: CNContactStore) {
   do {
  let groups = try store.groupsMatchingPredicate(nil)
    let predicate =  CNContact.predicateForContactsInGroupWithIdentifier(groups[0].identifier)
  //let predicate = CNContact.predicateForContactsMatchingName("John")
  let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName), CNContactEmailAddressesKey]


  let contacts = try store.unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch)
  self.objects = contacts
  dispatch_async(dispatch_get_main_queue(), { () -> Void in
    self.tableView.reloadData()
  })
} catch {
  print(error)
  }
}

func addExistingContact() {

}

override func viewWillAppear(animated: Bool) {
    self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed
    super.viewWillAppear(animated)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func insertNewObject(sender: NSNotification) {
    if let contact = sender.userInfo?["contactToAdd"] as? CNContact {
        objects.insert(contact, atIndex: 0)
        let indexPath = NSIndexPath(forRow: 0, inSection: 0)
        self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    }
}

// MARK: - Segues

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        if let indexPath = self.tableView.indexPathForSelectedRow {
            let object = objects[indexPath.row]
            let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
            controller.contactItem = object
            controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
            controller.navigationItem.leftItemsSupplementBackButton = true
        }
    }
}

// MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return objects.count
}

    override func tableView(tableView: UITableView, cellForRowAtIndexPath   indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

let contact = self.objects[indexPath.row]
let formatter = CNContactFormatter()

cell.textLabel?.text = formatter.stringFromContact(contact)
cell.detailTextLabel?.text = contact.emailAddresses.first?.value as? String

return cell
  }
       override func tableView(tableView: UITableView, canEditRowAtIndexPath    indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return false
  }
}
1

There are 1 best solutions below

1
On BEST ANSWER

This is how I currently get a list of the user's contacts and store them in a CNContact array.

let request = CNContactFetchRequest(keysToFetch: [CNContactEmailAddressesKey, CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)])

    var contacts = [CNContact]()
    do {
        try store.enumerateContactsWithFetchRequest(request) { contact, stop in
            contacts.append(contact)
        }

        self.objects = contacts
        NSOperationQueue.mainQueue().addOperationWithBlock({ 
            self.tableView.reloadData()
        })
    } catch {
        print(error)
    }

I'm assuming your problem is with the line groupsMatchingPredicate(nil), where you don't pass in a predicate so it can't find any matches. Just a thought.