Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

swift - Get iOS contact image with ABPersonCopyImageData

I'm trying to read the contact image of my iOS addressbook but I'm having some troubles with it.

I have a method that read the information of contacts of ABAddressBookRef and put it on a struct.

func readContacts(addressBook: ABAddressBookRef){
        let allPeople = ABAddressBookCopyArrayOfAllPeople(addressBookRef).takeRetainedValue() as NSArray
        var numeros : [Numeros] = []

        //lendo todos os contatos
        for person: ABRecordRef in allPeople{

            let firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as! String
            let lastName = ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue() as! String

            let phones : ABMultiValueRef = ABRecordCopyValue(person, kABPersonPhoneProperty).takeUnretainedValue() as ABMultiValueRef

            let data = ABPersonCopyImageData(person).takeRetainedValue() as NSData
            let imagemContato = UIImage(data: data)

            for(var numberIndex : CFIndex = 0; numberIndex < ABMultiValueGetCount(phones); numberIndex++) {
                let phoneUnmaganed = ABMultiValueCopyValueAtIndex(phones, numberIndex)

                let phoneNumber : NSString = phoneUnmaganed.takeUnretainedValue() as! NSString

                let locLabel : CFStringRef = (ABMultiValueCopyLabelAtIndex(phones, numberIndex) != nil) ? ABMultiValueCopyLabelAtIndex(phones, numberIndex).takeUnretainedValue() as CFStringRef : ""

                let cfStr:CFTypeRef = locLabel
                let nsTypeString = cfStr as! NSString
                let swiftString:String = nsTypeString as String

                //let customLabel = String (stringInterpolationSegment: ABAddressBookCopyLocalizedLabel(locLabel))

                let numero: Numeros = Numeros(tipoNumero: swiftString, numero: phoneNumber as String)

                numeros.append(numero)

            }

            let registroContato: Contato = Contato(primeiroNome: firstName, ultimoNome: lastName, contatoRecord: person, numeros: numeros, imagemContato: imagemContato!)

            contatos.append(registroContato)

        }
    }

but when I debug it, it stops on:

let data = ABPersonCopyImageData(person).takeRetainedValue() as NSData

and doesn't show any error message.

What am I doing wrong?

I'm using the simulator default contacts to test it, they did not have images but have the placeholder with his/her first letter of the name.

EDITED:

i've change the code to

let imagemContato: UIImage?
            if let data = ABPersonCopyImageData(person)?.takeRetainedValue() as? NSData     {
                print("(firstName) with image")
                imagemContato = UIImage(data: data)
            }
            else {
                print("(firstName) without image")
                imagemContato = UIImage(named: "UooQo.jpg")
            }

and on the console all contacts have no image:

console output: Kate without image Daniel without image John without image Anna without image Hank without image David without image

it shows no image for contact but i add one to John. contact image

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The AddressBook framework is one of the frameworks that is really nasty to use with Swift. First I'll point out that there is a new Contacts framework in iOS 9, which I would suggest you use if you have the option of not supporting 8 and earlier (AddressBook is deprecated as of iOS 9).

Having said that, the function ABPersonCopyImageData(ABRecord!) returns a value that has the type Unmanaged<CFData>!, which means that it is possible that it will be a nil value (it really should be Unmanaged<CFData>?, but I think Apple didn't bother fixing up AddressBook types because they were working on the Contacts framework instead. Given that it can and will return nil, you'll need to treat it like it could be nil even though it is an implicitly unwrapped type.

Change:

let data = ABPersonCopyImageData(person).takeRetainedValue() as NSData
let imagemContato = UIImage(data: data)

to:

let imagemContato: UIImage?
if let data = ABPersonCopyImageData(person)?.takeRetainedValue() as? NSData     {
    imagemContato = UIImage(data: data)
}
else {
    imagemContato = nil
}

Note: Later on in your code you force unwrap imagemContato when you create your Contato instance. You will have to handle the case where it is a nil value or your program will potentially crash when you do this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...