Zizoo
Zizoo

Reputation: 1764

How To Save a Contact Into The Contacts App in iOS - Swift

I'm trying to save a contact to the contacts app by using this code directly without requesting any permission:

import Foundation
import UIKit
import Contacts

@available(iOS 9.0, *)
class OnCallEmpContact: UITableViewController {

    var store: CNContactStore!

    @IBOutlet weak var nameLabel: UILabel!

    @IBOutlet weak var phoneLabel: UILabel!

    @IBOutlet weak var emailLabel: UILabel!

    @IBOutlet weak var workPhoneLabel: UILabel!



    var emp = employee()
    var rank = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        self.nameLabel.text=self.emp.getFistName()+" "+emp.getLastName()
        self.phoneLabel.text="0"+self.emp.getMobile()
        self.emailLabel.text=self.emp.getEmail()
        self.workPhoneLabel.text=self.emp.getPhone()

        store = CNContactStore()
        checkContactsAccess()


    }

    private func checkContactsAccess() {
        switch CNContactStore.authorizationStatusForEntityType(.Contacts) {
            // Update our UI if the user has granted access to their Contacts
        case .Authorized:
            self.accessGrantedForContacts()

            // Prompt the user for access to Contacts if there is no definitive answer
        case .NotDetermined :
            self.requestContactsAccess()

            // Display a message if the user has denied or restricted access to Contacts
        case .Denied,
        .Restricted:
            let alert = UIAlertController(title: "Privacy Warning!",
                message: "Permission was not granted for Contacts.",
                preferredStyle: .Alert)
            alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
            self.presentViewController(alert, animated: true, completion: nil)
        }
    }

    private func requestContactsAccess() {

        store.requestAccessForEntityType(.Contacts) {granted, error in
            if granted {
                dispatch_async(dispatch_get_main_queue()) {
                    self.accessGrantedForContacts()
                    return
                }
            }
        }
    }

    // This method is called when the user has granted access to their address book data.
    private func accessGrantedForContacts() {
        //Update UI for grated state.
        //...
    }


    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if section == 0{
        if rank == "0"{
        return "Primary Employee"
        }
        else if rank == "1"{
        return "Backup Employee"
        }
        }
        return""
    }

    override  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        tableView.deselectRowAtIndexPath(indexPath, animated: true) // to stop highliting the selected cell

        if indexPath.section==1 && indexPath.row==0{
                self.saveContact()
        }


    }



    func saveContact(){
        do{
            let contact = CNMutableContact()
        contact.givenName = self.emp.getFistName()
        contact.familyName = self.emp.getLastName()
        contact.phoneNumbers = [CNLabeledValue(
            label:CNLabelPhoneNumberiPhone,
            value:CNPhoneNumber(stringValue:emp.getMobile())),
                  CNLabeledValue(
                label:CNLabelPhoneNumberiPhone,
                value:CNPhoneNumber(stringValue:emp.getPhone()))]

        let workEmail = CNLabeledValue(label:CNLabelWork, value:emp.getEmail())
        contact.emailAddresses = [workEmail]


        let saveRequest = CNSaveRequest()
        saveRequest.addContact(contact, toContainerWithIdentifier:nil)
        try store.executeSaveRequest(saveRequest)
            print("saved")

        }

        catch{
            print("error")
        }
    }



}

I'm getting error at the last line try store.executeSaveRequest(saveRequest) of method saveContact

Error :

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=CNErrorDomain Code=100 "Access Denied" UserInfo={NSLocalizedDescription=Access Denied, NSLocalizedFailureReason=This application has not been granted permission to access Contacts.

I found the above code at apple website but also I red this on Privacy section in the middle :

Any call to CNContactStore will block the application while the user is being asked to grant or deny access

But nothing show up asking for access to the contacts app .. should I write more code to do this ? How ?

Upvotes: 3

Views: 7128

Answers (3)

Daniel Wijono
Daniel Wijono

Reputation: 86

This is the newest syntax from swift. Hope it helps !

           let store = CNContactStore()

            if CNContactStore.authorizationStatus(for: .contacts) == .notDetermined {
                store.requestAccess(for: .contacts) {granted, error in
                    if granted {
                        print("PERMISSION GRANTED")
                    } else {
                        print("PERMISSION NOT GRANTED")
                    }
                }
            } else if CNContactStore.authorizationStatus(for: .contacts) == .authorized {
                // If the user user has earlier provided the access, then add the contact
                print("AUTHORIZED")

                findContactsOnBackgroundThread { (contact) in
                    print("contacts : ",contact as Any)
                }
            } else {
                // If the user user has NOT earlier provided the access, create an alert to tell the user to go to Settings app and allow access
                print("NOT AUTHORIZED")
            }

Upvotes: 0

OOPer
OOPer

Reputation: 47896

Maybe you have read Contacts Framework Reference. You should think such overall description can be easily inaccurate in details. Check the latest reference.

CNContactStore has two methods related to authorization:

Privacy Access

+ authorizationStatusForEntityType:

- requestAccessForEntityType:completionHandler:

You should write something like this in your app:

var store: CNContactStore!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    store = CNContactStore()
    checkContactsAccess()
}

private func checkContactsAccess() {
    switch CNContactStore.authorizationStatusForEntityType(.Contacts) {
    // Update our UI if the user has granted access to their Contacts
    case .Authorized:
        self.accessGrantedForContacts()
        
    // Prompt the user for access to Contacts if there is no definitive answer
    case .NotDetermined :
        self.requestContactsAccess()
        
    // Display a message if the user has denied or restricted access to Contacts
    case .Denied,
         .Restricted:
        let alert = UIAlertController(title: "Privacy Warning!",
                                      message: "Permission was not granted for Contacts.",
                                      preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        self.presentViewController(alert, animated: true, completion: nil)
    }
}

private func requestContactsAccess() {
    
    store.requestAccessForEntityType(.Contacts) {granted, error in
        if granted {
            dispatch_async(dispatch_get_main_queue()) {
                self.accessGrantedForContacts()
                return
            }
        }
    }
}

// This method is called when the user has granted access to their address book data.
private func accessGrantedForContacts() {
    //Update UI for grated state.
    //...
}

Upvotes: -1

Mannopson
Mannopson

Reputation: 2684

It's wrong! Use do-catch statement and you'll be OK.

do {
  try store.executeSaveRequest(saveRequest)
} catch {}

Hope it helps.

Upvotes: 1

Related Questions