CNContactStore executeSaveRequest fails with CNErrorDomain Code=500

Area:

Contacts Framework


Summary:


When attempting to save a contact that has populated Social Profile data the following error is encountered: This is seen in iOS 11.3.1


In AddressBook on a device, I have a record linked to the Facebook and Twitter contact record. I fetch it into CNContact with CNContactFetchRequest, for detail code please find code :


@IBAction func btnSaveClick(_ sender: Any) {

//Create

if txtFname.text == "" {

Global.singleton.showWarningAlert(withMsg: "Please Enter First name")

return

}

else if txtName.text == "" {

Global.singleton.showWarningAlert(withMsg: "Please Enter Last name")

return

}

else if (txtCompany.text == "") {

Global.singleton.showWarningAlert(withMsg: "Please Enter Company name")

return

}

else if (txtTitle.text == "") {

Global.singleton.showWarningAlert(withMsg: "Please Enter Position")

return

}

var stop : Int = 0

for i in (0..<arrEmails.count){

let indexpath : IndexPath = IndexPath(row: i, section: 1)

let cell : EmailCell? = self.tblCreateContact.cellForRow(at: indexpath) as! EmailCell?

if (cell?.txtEmail.text != "") {

if !Global.singleton.validateEmail(strEmail: (cell?.txtEmail.text!)!){

Global.singleton.showWarningAlert(withMsg: "Please Enter proper email")

stop = 1

break

}

}

}

if stop == 1 {

return

}

var stopUrl : Int = 0

for i in (0..<arrURLs.count){

let indexpath : IndexPath = IndexPath(row: i, section: 2)

let cell : URLCell? = self.tblCreateContact.cellForRow(at: indexpath) as! URLCell?

if (cell?.txtURL.text != "") {

if cell!.txtURL.text!.range(of: "http") == nil {

cell!.txtURL.text = "http://\(cell!.txtURL.text!)"

}

if(self.validateUrl(stringURL: (cell?.txtURL.text)!)){

print("candidate is a well-formed url with")

} else {

stopUrl = 1

Global.singleton.showWarningAlert(withMsg: "Please Enter proper URL")

break

}

}

}

if stopUrl == 1 {

return

}

var stopCountry : Int = 0

for i in (0..<arrAddress.count){

let indexpath : IndexPath = IndexPath(row: i, section: 5)

let cell : AddressCell? = self.tblCreateContact.cellForRow(at: indexpath) as! AddressCell?

if cell?.txtCountry.text != "" {

if (self.isValidCountryInput(Input: (cell?.txtCountry.text!)!)){

}

else {

stopCountry = 1

Global.singleton.showWarningAlert(withMsg: "Please Enter proper Country Name")

break

}

}

}

if stopCountry == 1 {

return

}

let contact : CNMutableContact = CNMutableContact()

contact.givenName = txtName.text!

contact.familyName = txtFname.text!

contact.jobTitle = txtTitle.text!

contact.organizationName = txtCompany.text!

contact.emailAddresses = []

contact.phoneNumbers = []

for i in (0..<arrPhones.count){

let indexpath : IndexPath = IndexPath(row: i, section: 0)

let cell : PhoneCell? = self.tblCreateContact.cellForRow(at: indexpath) as! PhoneCell?

let shrO : ContactShare = arrPhones.object(at: i) as! ContactShare

if (cell?.txtPhone.text) != "" {

shrO.strValue = (cell?.txtPhone.text)!

shrO.strtype = (cell?.btnType.titleLabel?.text)!

if (i == 0) {

contact.phoneNumbers.append(CNLabeledValue(

label:CNLabelPhoneNumberMain,

value:CNPhoneNumber(stringValue:(cell?.txtPhone.text)!)))

}

else if (i==1) {

contact.phoneNumbers.append(CNLabeledValue(

label:CNLabelPhoneNumberMobile,

value:CNPhoneNumber(stringValue:(cell?.txtPhone.text)!)))

}

else {

contact.phoneNumbers.append(CNLabeledValue(

label:CNLabelPhoneNumberiPhone,

value:CNPhoneNumber(stringValue:(cell?.txtPhone.text)!)))

}

}

}

for i in (0..<arrEmails.count){

let indexpath : IndexPath = IndexPath(row: i, section: 1)

let cell : EmailCell? = self.tblCreateContact.cellForRow(at: indexpath) as! EmailCell?

if cell?.txtEmail.text != "" {

if !Global.singleton.validateEmail(strEmail: (cell?.txtEmail.text!)!){

Global.singleton.showSuccessAlert(withMsg: "Please Enter proper email")

break

}

}

let shrO : ContactShare = arrEmails.object(at: i) as! ContactShare

if (cell?.txtEmail.text) != nil {

shrO.strValue = (cell?.txtEmail.text)!

shrO.strtype = (cell?.btnType.titleLabel?.text)!

if shrO.strtype == "Work" {

let workEmail1 = CNLabeledValue(label:"WorkEmail", value:(cell?.txtEmail.text ?? "") as NSString)

contact.emailAddresses.append(workEmail1)

}

else{

let workEmail1 = CNLabeledValue(label:"Home", value:(cell?.txtEmail.text ?? "") as NSString)

contact.emailAddresses.append(workEmail1)

}

}

}

for i in (0..<arrURLs.count){

let indexpath : IndexPath = IndexPath(row: i, section: 2)

let cell : URLCell? = self.tblCreateContact.cellForRow(at: indexpath) as! URLCell?

let shrO : ContactShare = arrURLs.object(at: i) as! ContactShare

if (cell?.txtURL.text) != nil {

shrO.strValue = (cell?.txtURL.text)!

shrO.strtype = (cell?.btnType.titleLabel?.text)!

let workURL = CNLabeledValue(label:"URL", value:(cell?.txtURL.text ?? "") as NSString)

contact.urlAddresses.append(workURL)

}

}

for i in (0..<arrSocials.count){

let indexpath : IndexPath = IndexPath(row: i, section: 3)

let cell : SocialCell? = self.tblCreateContact.cellForRow(at: indexpath) as! SocialCell?

let shrO : ContactShare = arrSocials.object(at: i) as! ContactShare

if (cell?.txtSocial.text) != nil {

shrO.strValue = (cell?.txtSocial.text)!

shrO.strtype = (cell?.btnType.titleLabel?.text)!

if (shrO.strtype == "Facebook") {

let facebookProfile = CNLabeledValue(label: "Facebook", value: CNSocialProfile(urlString: shrO.strValue, username: "", userIdentifier: "", service: CNSocialProfileServiceFacebook))

contact.socialProfiles.append(facebookProfile)

}

else {

let twitterProfile = CNLabeledValue(label: "Twitter", value: CNSocialProfile(urlString: shrO.strValue, username: "", userIdentifier: "", service: CNSocialProfileServiceTwitter))

contact.socialProfiles.append(twitterProfile)

}

}

}

for i in (0..<arrInstantMsg.count){

let indexpath : IndexPath = IndexPath(row: i, section: 4)

let cell : InstantMsgCell? = self.tblCreateContact.cellForRow(at: indexpath) as! InstantMsgCell?

let shrO : ContactShare = arrInstantMsg.object(at: i) as! ContactShare

if (cell?.txtMessage.text) != nil {

shrO.strValue = (cell?.txtMessage.text)!

shrO.strtype = (cell?.btnType.titleLabel?.text)!

if (shrO.strtype == "Skype") {

let skypeProfile = CNLabeledValue(label: "Skype", value: CNInstantMessageAddress(username: shrO.strValue, service: CNInstantMessageServiceSkype))

contact.instantMessageAddresses.append(skypeProfile)

}

else if (shrO.strtype == "WhatsApp") {

let whatsAppProfile = CNLabeledValue(label: "WhatsApp", value: CNInstantMessageAddress(username: shrO.strValue, service: CNInstantMessageServiceFacebook))

contact.instantMessageAddresses.append(whatsAppProfile)

}

else {

let messagesProfile = CNLabeledValue(label: "Messages", value: CNInstantMessageAddress(username: shrO.strValue, service: CNInstantMessageServiceMSN))

contact.instantMessageAddresses.append(messagesProfile)

}

}

}

for i in (0..<arrAddress.count){

let indexpath : IndexPath = IndexPath(row: i, section: 5)

let cell : AddressCell? = self.tblCreateContact.cellForRow(at: indexpath) as! AddressCell?

let shrO : ContactAddressShare = arrAddress.object(at: i) as! ContactAddressShare

shrO.strLine1 = (cell?.txtAddressLine1.text)!

shrO.strLine2 = (cell?.txtAddressLine2.text)!

shrO.strCity = (cell?.txtCity.text)!

shrO.strState = (cell?.txtState.text)!

shrO.strCountry = (cell?.txtCountry.text)!

let homeAddress = CNMutablePostalAddress()

homeAddress.street = "\(shrO.strLine1)"

homeAddress.subLocality = "\(shrO.strLine2)"

homeAddress.city = shrO.strCity

homeAddress.state = shrO.strState

homeAddress.postalCode = ""

homeAddress.country = shrO.strCountry

contact.postalAddresses = [CNLabeledValue(label:CNLabelHome, value:homeAddress)]

}

for i in (0..<arrAboutMe.count){

if i == 0 {

let indexpath : IndexPath = IndexPath(row: i, section: 6)

let cell : AboutMeCell? = self.tblCreateContact.cellForRow(at: indexpath) as! AboutMeCell?

let shrO : ContactAboutMeShare = arrAboutMe.object(at: i) as! ContactAboutMeShare

if (cell?.txtAboutMe.text != "") {

shrO.strAboutMe = (cell?.txtAboutMe.text)!

contact.note = (cell?.txtAboutMe.text)!

}

else{

shrO.strAboutMe = ""

contact.note = ""

}

}

}

var vcard: String? = "BEGIN:VCARD\r\nVERSION:3.1"

let strName : String = "N:\(txtName.text ?? "")\n"

let strFullName : String = "FN:\(txtFname.text ?? "")\n"

let strOrgName : String = "ORG:\(txtTitle.text ?? "")\n"

let strposition : String = "TITLE:\(txtCompany.text ?? "")\n"

vcard = "\(vcard ?? "")\(strName)\(strFullName)\(strOrgName)\(strposition)"

for shrObjPhone in arrPhones {

let shrO : ContactShare = shrObjPhone as! ContactShare

vcard = "\(vcard ?? "")\n TEL;\(shrO.strtype):\(shrO.strValue)\n"

}

for shrObjEmail in arrEmails {

let shrO : ContactShare = shrObjEmail as! ContactShare

vcard = "\(vcard ?? "")\n EMAIL;\(shrO.strtype):\(shrO.strValue)\n"

}

for shrObjEmail in arrURLs {

let shrO : ContactShare = shrObjEmail as! ContactShare

vcard = "\(vcard ?? "")\n URL;\(shrO.strtype):\(shrO.strValue)\n"

}

for shrObjEmail in arrSocials {

let shrO : ContactShare = shrObjEmail as! ContactShare

vcard = "\(vcard ?? "")\n LABEL;TYPE=\(shrO.strtype):\(shrO.strValue)\n"

}

for shrObjEmail in arrInstantMsg {

let shrO : ContactShare = shrObjEmail as! ContactShare

vcard = "\(vcard ?? "")\n LABEL;TYPE=\(shrO.strtype):\(shrO.strValue)\n"

}

for shrObjadd in arrAddress {

let shrO : ContactAddressShare = shrObjadd as! ContactAddressShare

vcard = "\(vcard ?? "")\n ADR;WORK;POSTAL=\(shrO.strLine1);\(shrO.strLine2);\(shrO.strCity);\(shrO.strState);\(shrO.strCountry)\n"

}

for shrObjabout in arrAboutMe {

let shrO : ContactAboutMeShare = shrObjabout as! ContactAboutMeShare

vcard = "\(vcard ?? "")\n NOTE=\(shrO.strAboutMe)\n"

}

vcard = "\(vcard ?? "")END:VCARD"

print("vcard data=\(vcard ?? "")")

do {

let saveRequest = CNSaveRequest()

saveRequest.add(contact, toContainerWithIdentifier: contactStore.defaultContainerIdentifier())

try contactStore.execute(saveRequest)

Global.singleton.saveToUserDefaults(value: contactStore.defaultContainerIdentifier(), forKey: "MyCardContactId")

let vcardFromContacts = try? CNContactVCardSerialization.data(with: [contact]) as NSData

var vCardData: Data? = try? CNContactVCardSerialization.data(with: ([contact]))

let vCardNote: String? = contact.note

if vCardNote == "" {

} else {

vCardData = CNContactVCardSerialization.vcardDataAppendingNote(vcard: vcardFromContacts! as Data, noteasString:vCardNote!)

}

Global.singleton.saveToUserDefaultsWithContactObject(contact: vCardData!, forKey: Global.kQRAppSettingKeys.MyContactDetail)

} catch {

print("\(error.localizedDescription)")

if error.localizedDescription == "Access Denied" {

Global.singleton.showWarningAlert(withMsg:"Unable to save the new contact. Please grant your contact permission. You have \(error.localizedDescription) your contact permission.")

} else {

Global.singleton.showWarningAlert(withMsg:"Unable to save the new contact. \(error.localizedDescription)")

}

return

}

do {

let vcardFromContacts = try CNContactVCardSerialization.data(with: [contact]) as NSData

//var error: Error? = nil

var vCardData: Data? = try? CNContactVCardSerialization.data(with: ([contact]))

let vCardNote: String? = contact.note

if vCardNote == "" {

} else {

vCardData = CNContactVCardSerialization.vcardDataAppendingNote(vcard:vcardFromContacts as Data, noteasString:vCardNote!)

}

let lastSavedContact = String(data: vCardData ?? Data(), encoding: .utf8)!

print("added contact = \(String(describing: lastSavedContact))")

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let viewController1 : CreateVCardVC = storyboard.instantiateViewController(withIdentifier :"CreateVCardVC") as! CreateVCardVC

viewController1.lastSavedContact = lastSavedContact

viewController1.lastSavedCON = contact

Global.singleton.saveToUserDefaults(value: lastSavedContact, forKey: Global.myBusinessCard)

Global.singleton.saveToUserDefaults(value: "1", forKey: Global.IsCreatedBusinessCard)

self.navigationController?.pushViewController(viewController1 , animated: true)

} catch {

Global.singleton.showWarningAlert(withMsg:"Error \(error.localizedDescription)" )

}

}




On execute executeSaveRequest, I caught an error:


NSError with domain: CNErrorDomain, error:500


The question: Is it possible to modify the linked contact (not unified), and if it is, what I do wrong?


If I modifying not linked contact - all OK!


Expected Results:

- Need to save in iOS contact list

Actual Results:

- CNErrorDomain, code:500

Replies

I have this error when the Contacts app is configured to store contacts in an Exchange account. When I choose an iCloud account as a default it immediately saves a contact well. I can check what is set on your device in Settings -> Contacts -> Default Account