Search code examples
iosswiftcontacts

iOS AddressBook - get contact image crash


There is some problem with AddressBook which I can't reproduce, code works on my iPhone and iPad, this happens on client phone and result in app crash. As far as I can see from Crashlytics problem should be in following line:

let data = ABPersonCopyImageDataWithFormat(contact, kABPersonImageFormatThumbnail).takeRetainedValue()

Here is complete code for reading address book:

    var err : Unmanaged<CFError>? = nil
    let addressBookRef : ABAddressBook? = ABAddressBookCreateWithOptions(nil, &err).takeRetainedValue()
    if addressBookRef == nil {
        print(err)
        return
    }

    let contacts = ABAddressBookCopyArrayOfAllPeople(addressBookRef).takeRetainedValue() as NSArray as [ABRecord]
    for contact in contacts {
        let firstName = ABRecordCopyValue(contact, kABPersonFirstNameProperty)?.takeRetainedValue() as? String
        let lastName = ABRecordCopyValue(contact, kABPersonLastNameProperty)?.takeRetainedValue() as? String

        var image: UIImage?
        if ABPersonHasImageData(contact) {

            let data = ABPersonCopyImageDataWithFormat(contact, kABPersonImageFormatThumbnail).takeRetainedValue()
            if let img = UIImage(data: data) {
                image = img
            }

        }


        …
}

Do you have any suggestions what could happen on clients phone so I can reproduce this error? Is it possible that some contact is corrupt? How should I handle this?

I've seen this post Get iOS contact image with ABPersonCopyImageData that ABPersonCopyImageData could return nil, I tried to handle that but app is still crashing.


Solution

  • check all for nil. if ABPersonCopyImageDataWithFormat returns nil, you call takeRetainedValue on nil. and then use it nil to create image too

    guard let CFData = ABPersonCopyImageDataWithFormat(contact, kABPersonImageFormatThumbnail) else {
        print("no cfdata")
        return
    }
    
    if let data = CFData.takeRetainedValue {
         if let img = UIImage(data: data) {
             image = img
         }
    }