Omarj
Omarj

Reputation: 1159

ABPersonCopyImageDataWithFormat deletes contacts image

I have this code to store all contacts image in dictionary. But, in some cases when it is interrupted, the image for contacts just disappear.

dispatch_async(dispatch_get_main_queue(), ^{            

        if (ABPersonHasImageData(_personObj)) {

            // UIImage *image = [UIImage imageWithData:(__bridge NSData*) ABPersonCopyImageDataWithFormat(_personObj, kABPersonImageFormatThumbnail)];
            NSData *data = (__bridge NSData *) ABPersonCopyImageDataWithFormat(_personObj, kABPersonImageFormatThumbnail);
            UIImage *image = [UIImage imageWithData:data scale:1];
            int recordId = ABRecordGetRecordID(_personObj);
            [contactImagesDi setValue:image forKey:[NSNumber numberWithInt:recordId]];

        }

});

Upvotes: 2

Views: 1028

Answers (1)

Rob Napier
Rob Napier

Reputation: 299265

A single ABPerson is not threadsafe. You cannot pass an ABPerson to a background queue using dispatch_async(). If you want to do background processing, you must generate a new ABAddressBook on each thread and use ABPerson records fetched from that address book on that thread.

If you need to logically pass an ABPerson between threads, you need to fetch its ID with ABRecordGetRecordID(). You can pass that and reconstruct a new ABPerson record on the other thread (with its own address book) using ABAddressBookGetPersonWithRecordID().

@try/@catch is very rare in ObjC, and you should have a very good reason for doing it. Under ARC, you will generally leak memory. Exceptions are meant to indicate that the program is in trouble and should crash shortly.

You are leaking data. You should be using CFBridgingRelease() here, not __bridge. You need to balance the Copy.

Your modification of contactImagesDi is very dangerous, assuming this is a dictionary. NSMutableDictionary is not threadsafe. If it is an object that you are using KVC on, then it could be thread-safe, but only if you have taken some pains to ensure that. Typically the better solution is to use dispatch_async to put that kind of update back onto the main thread.

Upvotes: 6

Related Questions