Updating city in iOS Contacts postalAddress

Hi all, I’m new to iOS (Swift) development, and I’ve been tinkering with this all week. I am trying to update only the city of the postal addresses of a contact from iOS Contacts, and leave the rest of the postal address (street, ZIP code, etc.) intact. I figured I could just get a mutable copy of the

contact.postalAddress
using
postalAddress.mutableCopy()
, and then write to
mutableCopy.city = “New City”
. However, when I try this I get a -[CNLabeledValue mutableCopyWithZone:]: unrecognized selector sent to instance error. My current solution is to create a new address filled with values from the old address, but it seems there should be a better way (like copying the old address and just changing the city, like I’m trying to do). Is there something I’m missing? Thanks!


So, what I want to work:

  
 
func updateContact(contact: CNContact) -> BooleanLiteralType{
    var success = false
    let store = CNContactStore()


    do {
        let updContact = contact.mutableCopy() as! CNMutableContact
        var addrArray  = [CNLabeledValue<CNPostalAddress>]()
        for postAddress in updContact.postalAddresses{
            let curLabel = postAddress.label
            var address = postAddress.mutableCopy() as! CNMutablePostalAddress
            address.city = "Cityville"


            let curAddrLabeledVal = CNLabeledValue<CNPostalAddress>(label:curLabel, value:address)
            addrArray.append(curAddrLabeledVal)
        }


        updContact.postalAddresses = addrArray
        let req = CNSaveRequest()
        req.update(updContact)
        try store.execute(req)
        success = true
    }
    catch let err{
        print(err)
    }
    return success
}

This results in the following exception:


2020-05-26 00:06:19.537517+0200 My App[78089:4168944] -[CNLabeledValue mutableCopyWithZone:]: unrecognized selector sent to instance 0x600001388b80
2020-05-26 00:06:19.545537+0200 My App[78089:4168944] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CNLabeledValue mutableCopyWithZone:]: unrecognized selector sent to instance 0x600001388b80'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23e3cf0e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff50ba89b2 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23e5dc34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    3   CoreFoundation                      0x00007fff23e4190c ___forwarding___ + 1436
    4   CoreFoundation                      0x00007fff23e43bf8 _CF_forwarding_prep_0 + 120
    5   My App                              0x00000001015b4898 $s12My_App13updateContact7contactSbSo9CNContactC_tF + 1048
    6   My App                              0x00000001015bf3f1 $s12My_App11ContentViewV4bodyQrvg7SwiftUI05TupleD0VyAE0D0PAEE7opacityyQrSdFQOyAiEE5frame5width6height9alignmentQr12CoreGraphics7CGFloatVSg_ArE9AlignmentVtFQOyAA11ProgressBarV_Qo__Qo__AE010NavigationD0VyAiEE010navigationS5Items7leading8trailingQrqd___qd_0_tAeHRd__AeHRd_0_r0_lFQOyAiEE0uS5TitleyQrAE4TextVFQOyAE4ListVys5NeverOAE7ForEachVySaySo9CNContactCGSSAE6HStackVyAE0T4LinkVyAA10ContactRowVAA13ContactDetailVGGGG_Qo__AE6ButtonVyA4_GA29_Qo_GtGyXEfU_A30_yXEfU_yycfU2_yycfU_ + 465
    7   My App                              0x00000001015bf8f0 $sIeg_IeyB_TR + 48
    8   libdispatch.dylib                   0x0000000101877f11 _dispatch_call_block_and_release + 12
    9   libdispatch.dylib                   0x0000000101878e8e _dispatch_client_callout + 8
    10  libdispatch.dylib                   0x000000010187b2d8 _dispatch_queue_override_invoke + 1022
    11  libdispatch.dylib                   0x000000010188a399 _dispatch_root_queue_drain + 351
    12  libdispatch.dylib                   0x000000010188aca6 _dispatch_worker_thread2 + 135
    13  libsystem_pthread.dylib             0x00007fff51c089f7 _pthread_wqthread + 220
    14  libsystem_pthread.dylib             0x00007fff51c07b77 start_wqthread + 15
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)


This is the solution that works, but as you can see it’s not really what I want as it requires me to define all postalAddress attributes:


func updateContact(contact: CNContact) -> BooleanLiteralType{
    var success = false
    let store = CNContactStore()


    do {
        let updContact = contact.mutableCopy() as! CNMutableContact
        var addrArray  = [CNLabeledValue<CNPostalAddress>]()
        for postAddress in updContact.postalAddresses{
            let curLabel = postAddress.label
            let address = CNMutablePostalAddress()
            address.street = postAddress.value.street
            address.city = "Cityville"
            address.postalCode = postAddress.value.postalCode
            address.state = postAddress.value.state
            address.country = postAddress.value.country
            address.isoCountryCode = postAddress.value.isoCountryCode
            address.subAdministrativeArea = postAddress.value.subAdministrativeArea
            address.subLocality = postAddress.value.subLocality


            let curAddrLabeledVal = CNLabeledValue<CNPostalAddress>(label:curLabel, value:address)
            addrArray.append(curAddrLabeledVal)
        }


        updContact.postalAddresses = addrArray
        let req = CNSaveRequest()
        req.update(updContact)
        try store.execute(req)
        success = true
    }
    catch let err{
        print(err)
    }
    return success
}


Any help is much appreciated!