How to dismiss and _save_ CNContactViewController(forNewContact...)?

I'm using the new CNContactViewController in my Swift 2/iOS 9 app, and have it working great as a contact picker. However, I can't get it work as a contact _editor_ for the simple reason that it doesn't have a "Done" button (only a "Cancel") button. I'd hoped that the new beta (6) of Xcode 7 would either add a "Done" button (or option for one) to the CNContactViewController(forNewContact...), but no such luck. Nor can I find anything in the newly-revised CNContactViewController docs indicating how to dismiss the controller and effect a save of the edited contact.


Here's how I present that controller:


func performContactEdit()

{

let currentContactViewController = CNContactViewController(forNewContact: suppliedContact!)

currentContactViewController.delegate = self

currentContactViewController.modalPresentationStyle = .FormSheet

presentViewController(currentContactViewController, animated: true, completion: nil)

}


This presents the editor just fine, and I can enter and edit information, I just can't save it! There's only a "Cancel" button in the presented form, no "Done" button.


Has anyone figured this out? Have I overlooked something (possibly obvious)?


Thanks!


Carl

I'm also struggling with Contacts/ContactsUI frameworks, and have not yet succeeded to make them work as expected.

But, with this code, I believe you can see Done button.

    private func showNewContactViewController() {
        let npvc = CNContactViewController(forNewContact: nil)
        npvc.delegate = self
       
        let navigation = UINavigationController(rootViewController: npvc)
        self.presentViewController(navigation, animated: true, completion: nil)
    }

The above code follows the way of an old AddressBookUI sample code: QuickContacts.


EDIT: I think I should add a few more things.

            let cvc = CNContactViewController(forContact: contact)
            cvc.delegate = self
            cvc.allowsEditing = true
            self.navigationController?.pushViewController(cvc, animated: true)

This code is also derived from the sample code above in a method editing existing contact.


- If you want to edit an existing contact, you should use init(forContact:) rather than init(forNewContact:)

- You need to set allowsEditing to true, if you need to make your CNContactViewController editable

Thanks for the quick reply! I thought for sure that you'd solved it, but unfortunately, so far as I can tell, it still doesn't work.


For creating and editing a new contact, I tried:


        let newContactViewController = CNContactViewController(forNewContact: nil)
        newContactViewController.delegate = self

        let store = CNContactStore()
        newContactViewController.contactStore = store
        newContactViewController.allowsEditing = true

        if contactRequestRequiresName
        {
            newContactViewController.highlightPropertyWithKey(CNContactGivenNameKey, identifier: nil)
        }

        let navigationController = UINavigationController(rootViewController: newContactViewController)
        navigationController.modalPresentationStyle = .FormSheet

        presentViewController(navigationController, animated: true, completion: nil)


Unforunately, even though this presents an editable version of a new contact, there is no "Done" button, only a "Cancel" button, so you can't save the edits.


For editing an existing contact, I tried:


        let currentContactViewController = CNContactViewController(forContact: suppliedContact!)
        currentContactViewController.delegate = self


        let store = CNContactStore()
        newContactViewController.contactStore = store
        newContactViewController.allowsEditing = true

        let navigationController = UINavigationController(rootViewController: newContactViewController)
        navigationController.modalPresentationStyle = .FormSheet
  
        presentViewController(navigationController, animated: true, completion: nil)


But this, too, doesn't work: it presents a _read-only_ view of the given contact, not an editable view (and still no "Done" button)

(By the way, in neither case does the presence or absence of newContactViewController.allowsEditing = true make any difference: according to the docs, it's set to true by default anyways.)


Still, thanks for trying! If anyone out there has actually managed to create a CNContact programatically, I'd love to see your code!


Carl

Accepted Answer

Another possibility is lack of requesting access:

    override func viewDidLoad() {
        super.viewDidLoad()
        //
        store = CNContactStore()
        checkContactsAccess()
    }
   
    private func checkContactsAccess() {
        switch CNContactStore.authorizationStatusForEntityType(.Contacts) {
            //
        case .Authorized:
            self.accessGrantedForContacts()
           
            //
        case .NotDetermined :
            self.requestContactsAccess()
           
            //
        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
                }
            }
        }
    }

(You may find whole project with searching `MyContacts-Swift` in the GitHub.)

You are quite correct! My mistake was in thinking that since the iOS 9 simulator gave one access to its pseudo-contacts without requiring authentication, it would also let you edit and save without auth. That is mistaken, and the behavior of the CNContactViewController is quite puzzling until you realize this and do the auth.


Thank you very much for the replies, and the code!


Carl

How to dismiss and _save_ CNContactViewController(forNewContact...)?
 
 
Q