Reputation: 1159
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
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