Search code examples
iosmacoscncontact

CNContact unifiedContact broken with Mac OS Sierra


Since I switched to Mac OS Sierra and XCode 8, code that was using unifiedContactsMatchingPredicate:keysToFetch:error: or unifiedContactWithIdentifier:keysToFetch:error: no longer run correctly.

An error is returned : Error domain: CNErrorDomain code: 200 With a description saying the record does not exist, or the update of the record failed.

All codes were working fine with Mac OS 10.11 and XCode 7, read access to address book are granted and the CNContact I am looking for does exist.

I had the same behavior with iOS 10, which I solved by adding a NSContactsUsageDescription key in the plist file (that was optional before iOS 10, but no longer). I did the same in my mac OS plist file with no luck.

Any clue what's going on and where to search ?

EDIT : with some code :

I wrote 2 new projects, one in Objective-C, one in Swift. Both of them give the same result.

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application

CNContactStore  *contactStore   = [[CNContactStore alloc] init] ;
NSPredicate     *predicate      = [CNContact predicateForContactsMatchingName:@"TEST_CONTACT"] ;
NSError         *error          = nil ;

NSArray         *keys           = @[
                                    CNContactGivenNameKey,
                                    CNContactFamilyNameKey
                                    ] ;

NSArray         *contacts       = [contactStore unifiedContactsMatchingPredicate:predicate
                                                                     keysToFetch:keys
                                                                           error:&error] ;
NSLog(@"%d contacts found : %@",[contacts count],contacts) ;

}

and

func applicationDidFinishLaunching(_ aNotification: Notification) {
    // Insert code here to initialize your application

    let contactStore    = CNContactStore()
    let predicate       = CNContact.predicateForContacts(matchingName: "TEST_CONTACT")


    let keys            = [CNContactGivenNameKey,CNContactFamilyNameKey]

    do
    {
        let contacts        = try contactStore.unifiedContacts(matching: predicate,
                                                               keysToFetch: keys as [CNKeyDescriptor])
        print(contacts)
    }
    catch
    {
        print("caught an error")
    }

}

Result shown in the console :

2016-09-27 17:19:48.797029 TestCNContact.swift[13675:3502046] [core] __42-[ACAccountStore accountsWithAccountType:]_block_invoke_2 (208) "Error returned from daemon: <private>"

2016-09-27 17:19:48.798105 TestCNContact.swift[13675:3502046] [core] __42-[ACAccountStore accountsWithAccountType:]_block_invoke_2 (208) "Error returned from daemon: " [] 2016-09-27 17:19:49.631876 TestCNContact.swift[13675:3502047] [error] warning: dynamic accessors failed to find @property implementation for 'uniqueId' for entity ABCDInfo while resolving selector 'uniqueId' on class 'ABCDInfo'. Did you remember to declare it @dynamic or @synthesized in the @implementation ? 2016-09-27 17:19:52.637627 TestCNContact.swift[13675:3502047] [error] warning: dynamic accessors failed to find @property implementation for 'serialNumber' for entity ABCDAddressBookSource while resolving selector 'serialNumber' on class 'ABCDAddressBookSource'. Did you remember to declare it @dynamic or @synthesized in the @implementation ? 2016-09-27 17:19:52.739108 TestCNContact.swift[13675:3502068] [error] warning: dynamic accessors failed to find @property implementation for 'uniqueId' for entity ABCDAddressBookSource while resolving selector 'uniqueId' on class 'ABCDAddressBookSource'. Did you remember to declare it @dynamic or @synthesized in the @implementation ?


Solution

  • I found a solution !!!

    Apple has answered my radar with the following statement : "Contacts now requires that anyone using it be codesigned with the uses-contacts entitlement."

    So what I did is that I sandboxed my app, and granted the "Contacts access" entitlement. Everything works fine again.

    enter image description here

    It seems Apple will no longer accept non sandboxed app to access the Contacts (or location or calendar).