1

I have a Xamarin.Forms App where I like to open the Add Contact Screen. I used the Depedency Service to do this. It works fine on Android but every time I run it on my iPhone, it crashes. My sample code is below.

public bool SaveContactAsync(Profile ContactToSave)
        {
            var store = new CNContactStore();
            var contact = new CNMutableContact();
            var cellPhone = new CNLabeledValue<CNPhoneNumber>(CNLabelPhoneNumberKey.Mobile, new CNPhoneNumber(ContactToSave.PhoneNumber));
            var phoneNumber = new[] { cellPhone };
            contact.PhoneNumbers = phoneNumber;
            contact.GivenName = ContactToSave.FirstName;
            contact.FamilyName = ContactToSave.LastName;
            var emailAddress = new CNLabeledValue<NSString>(CNLabelKey.Other, new NSString(ContactToSave.EmailAddress));
            contact.EmailAddresses = new CNLabeledValue<NSString>[] { emailAddress };
            var saveRequest = new CNSaveRequest();
            saveRequest.AddContact(contact, store.DefaultContainerIdentifier);

            NSError error;
            if (store.ExecuteSaveRequest(saveRequest, out error))
            {
                return true;
            }
            else
            {
                return false;
            }

        }

The application crashes once it get to saveRequest.AddContact(contact, store.DefaultContainerIdentifier);. What could I be doing wrong? I looked at the App Center Diagnostics, here's what I saw.

libsystem_kernel.dylib
__abort_with_payload
libsystem_kernel.dylib
abort_with_payload
TCC
__CRASHING_DUE_TO_PRIVACY_VIOLATION__
TCC
__TCCAccessRequest_block_invoke.124
TCC
__tccd_send_message_block_invoke
libxpc.dylib
_xpc_connection_reply_callout
libxpc.dylib
_xpc_connection_call_reply_async
libdispatch.dylib
_dispatch_client_callout3
libdispatch.dylib
_dispatch_mach_msg_async_reply_invoke$VARIANT$mp
libdispatch.dylib
_dispatch_kevent_worker_thread
libsystem_pthread.dylib
_pthread_wqthread
libsystem_pthread.dylib
start_wqthread
Dara Oladapo
  • 586
  • 6
  • 12

1 Answers1

3

CRASHING_DUE_TO_PRIVACY_VIOLATION

It seems that you didn't add the Contact permission to your app .

Add the following code to the info.plist in iOS project.

<key>NSContactsUsageDescription</key>  
<string>Your app needs access your Contact</string> 

And in Depedency Service

   public bool CheckPermission()
    {

        CNAuthorizationStatus status = CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts);

        if(status==CNAuthorizationStatus.NotDetermined)
        {
            // need request permission
            CNContactStore store = new CNContactStore();
            store.RequestAccess(CNEntityType.Contacts,null);

        }
        else if(status == CNAuthorizationStatus.Restricted|| status == CNAuthorizationStatus.Denied)
        {
            Console.WriteLine("user restricted the permission");
        }

        else if(status==CNAuthorizationStatus.Authorized)
        {
            return true;
        }
        return false;
    }
var hasPermission = CheckPermission();
if(hasPermission)
{
   SaveContactAsync(profile);
}

For more details about iOS permission you could check Complete list of iOS app permissions

Lucas Zhang
  • 18,630
  • 3
  • 12
  • 22
  • Thank you Lucas, I did that, now I get a new kind of error. SIGABRT: Value cannot be null. Parameter name: completionHandler I'm guessing it's coming from store.RequestAccess(CNEntityType.Contacts,null); – Dara Oladapo Jan 10 '20 at 19:39
  • Got it working now. I changed store.RequestAccess(CNEntityType.Contacts,null); to store.RequestAccessAsync(CNEntityType.Contacts); – Dara Oladapo Jan 10 '20 at 21:04