Search code examples
iosswift3abaddressbookxcode8opaque-pointers

ABAddressBook fromOpaque(_:) in Swift 3


So I've just updated to Xcode 8 and converted my Swift 2.3 code to Swift 3, and I have an error in this line of code that wasn't in Swift 2.3:

func populateFrom(_ addressBook:ABAddressBook)
{
    let allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()
    let nPeople = ABAddressBookGetPersonCount(addressBook)
    for index in 0..<nPeople
    {
       let person:ABRecord = Unmanaged<ABRecord>.fromOpaque(OpaquePointer(CFArrayGetValueAtIndex(allPeople, index))).takeUnretainedValue()
    }
}

Now the problem is in line let person:ABRecord = Unmanaged<ABRecord>.fromOpaque(OpaquePointer(CFArrayGetValueAtIndex(allPeople, index))).takeUnretainedValue()

Xcode tells me that 'fromOpaque' is unavailable: use 'fromOpaque(_:UnsafeRawPointer)' instead. But I can't find that function Xcode is telling me to use, I can just find fromOpaque(value: UnsafeRawPointer) which is the one I'm currently using.

How can I make this work?


Solution

  • You can simplify this a bit, eliminating all of those opaque pointer references, e.g.:

    func populate(from addressBook: ABAddressBook) {
        let allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() as [ABRecord]
        for person in allPeople {
            let name = ABRecordCopyCompositeName(person).takeRetainedValue()
            print(name)
        }
    }
    

    Or, given that the AddressBook framework was deprecated in iOS 9, you can use the Contacts framework:

    let store = CNContactStore()
    store.requestAccess(for: .contacts) { granted, error in
        guard granted else {
            print(error)
            return
        }
    
        self.populate(from: store)
    }
    

    And

    func populate(from store: CNContactStore) {
        let formatter = CNContactFormatter()
        formatter.style = .fullName
    
        let request = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: formatter.style)])
        do {
            try store.enumerateContacts(with: request) { contact, stop in
                print(formatter.string(from: contact))
            }
        } catch {
            print(error)
        }
    }