1

I took a look at the SE question here [Avinash's answer] and the Apple resource here [bottom of page 18 and top of page 19] in my attempt to set an address for an ABRecord. I did my best to translate them from Objective-C, but apparently I made an mistake somewhere since on the line let dict = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) I get the error Cannot assign to immutable value of type 'CFDictionaryValueCallBacks'.

Here's my code:

    let information: ABRecord = ABPersonCreate().takeRetainedValue()

    let address: ABMutableMultiValueRef = ABMultiValueCreateMutable(ABPropertyType(kABMultiDictionaryPropertyType)).takeUnretainedValue()

    var keys = [CFStringRef]()
    var values = [CFStringRef]()

    keys.append(kABPersonAddressStreetKey)
    keys.append(kABPersonAddressCityKey)
    keys.append(kABPersonAddressStateKey)
    keys.append(kABPersonAddressZIPKey)
    keys.append(kABPersonAddressCountryKey)
    keys.append(kABPersonAddressCountryCodeKey)

    Note: country code left out

    values.append(s["kABPersonAddressStreetKey"]!! as NSString)
    values.append(s["kABPersonAddressCityKey"]!! as NSString)
    values.append(s["kABPersonAddressStateKey"]!! as NSString)
    values.append(s["kABPersonAddressZIPKey"]!! as NSString)
    values.append(s["kABPersonAddressCountryKey"]!! as NSString)
    values.append(s["kABPersonAddressCountryCodeKey"]!! as NSString)

    let dict = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)

    let scanned = ABUnknownPersonViewController()

    let identifier = ABMultiValueIdentifier()

    ABMultiValueAddValueAndLabel(address, dict, kABHomeLabel, &identifier)

    ABRecordSetValue(information, kABPersonAddressProperty, address, nil)
Community
  • 1
  • 1
Randoms
  • 2,110
  • 2
  • 20
  • 31
  • You will find it a lot easier to work in the NSDictionary world instead of the CFDictionary world. There is absolutely no need for anything but NSDictionary here. Just form the dictionary in normal Swift. – matt Aug 11 '15 at 03:34
  • @matt Hi, thanks for the tip. I tried `let dict: NSDictionary = [kABPersonAddressStreetKey : s["kABPersonAddressStreetKey"]!! as NSString,...`, but got an error saying that there was no overload for subscript which accepts the following arguments. Could you or anyone else possibly provide a little sample code as to how to implement your suggestion? – Randoms Aug 11 '15 at 14:05
  • What is `s`? It looks like it is already the dictionary you want. – matt Aug 11 '15 at 14:29
  • @matt It's a regular (not NS) dictionary of type [String : String?], which holds a lot more information besides the address. Also, the keys are of type String, and not ABProperty, so I'm not sure if it would work unmodified – Randoms Aug 11 '15 at 15:57
  • Okay, but let me get this straight. You are having trouble forming the dictionary based on `s`. You want someone to help you fix that trouble so your code will compile. But you are not willing to show what `s` actually is? – matt Aug 11 '15 at 16:13

1 Answers1

1

I'm sure there's a much more concise way to do this, but here's the solution I've come up with.

 var addressComponents = [String : String]()

    if let value = s["kABPersonAddressStreetKey"] {
        addressComponents[kABPersonAddressStreetKey as String] =  value
    }

    if let value = s["kABPersonAddressCityKey"] {
        addressComponents[kABPersonAddressCityKey as String] = value
    }

    if let value = s["kABPersonAddressStateKey"] {
        addressComponents[kABPersonAddressStateKey as String] = value
    }

    if let value = s["kABPersonAddressZIPKey"] {
        addressComponents[kABPersonAddressZIPKey as String] = value
    }

    if let value = s["kABPersonAddressCountryKey"] {
        addressComponents[kABPersonAddressCountryKey as String] = value
    }

    if let value = s["kABPersonAddressCountryCodeKey"] {
        addressComponents[kABPersonAddressCountryCodeKey as String] = value
    }

    let address: ABMutableMultiValue = ABMultiValueCreateMutable(ABPropertyType(kABMultiStringPropertyType)).takeRetainedValue()
    ABMultiValueAddValueAndLabel(address, addressComponents, kABHomeLabel, nil)
    ABRecordSetValue(information, kABPersonAddressProperty, address, nil)
Randoms
  • 2,110
  • 2
  • 20
  • 31