I have this code for searching in the AddressBook and xcode suggests me that i have potential leaks in firstName, lastName, and another object that is unknown even to xcode. I tried to release the first 2 of them and the warning disappears but my app is crashing. Also i have a random crash on this line, i got it only once but appears in crashlytics for other people. Do you see anything wrong with my code? Thanks.
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonPhoneProperty);
The code. It's purpose is to group all the contacts by the first letter of the name and to duplicate the contacts in case they have multiple numbers.
- (void)filterByKeyword:(NSString*)keyword completionBlock:(AddressBookSearchCompletionBlock)completionBlock {
dispatch_async(abQueue, ^{
[self.filteredContacts removeAllObjects];
// Iterate over original contacts
for (id evaluatedObject in self.allContacts) {
CFStringRef n = ABRecordCopyCompositeName((__bridge ABRecordRef)evaluatedObject);
NSString *name = (__bridge_transfer NSString*)n;
if (name == nil) {
RCLog(@"name is nil. skip this contact");
continue;
}
if (keyword == nil || [[name lowercaseString] rangeOfString:keyword].location != NSNotFound)
{
NSString *key = [[name substringToIndex:1] uppercaseString];
if (key == nil || [key isEqualToString:@"_"]) {
key = @"#";
}
NSMutableArray *arr = [self.filteredContacts objectForKey:key];
if (arr == nil) {
arr = [[NSMutableArray alloc] init];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonPhoneProperty);
signed long num = ABMultiValueGetCount(phoneNumbers);
if (num == 0) {
[arr addObject:evaluatedObject];
}
else {
for (CFIndex i = 0; i < num; i++) {
if (i > 0) {
// Create a separate contact with the alternative phone numbers of a contact
NSString* phoneNumber = (__bridge_transfer NSString*) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSString* phoneNumericNumber = [phoneNumber stringByTrimmingCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
if (phoneNumber != nil && phoneNumber.length > 0 && phoneNumericNumber.length > 0) {
ABRecordRef persona = ABPersonCreate();
CFStringRef firstName = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonLastNameProperty);
ABRecordSetValue (persona, kABPersonFirstNameProperty, firstName, nil);
ABRecordSetValue (persona, kABPersonLastNameProperty, lastName, nil);
ABMutableMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
bool didAddPhone = ABMultiValueAddValueAndLabel(multiPhone, (__bridge CFTypeRef)(phoneNumber), kABPersonPhoneMobileLabel, NULL);
if (didAddPhone){
ABRecordSetValue(persona, kABPersonPhoneProperty, multiPhone, nil);
}
if (ABPersonHasImageData((__bridge ABRecordRef)evaluatedObject)) {
ABPersonSetImageData(persona, ABPersonCopyImageDataWithFormat((__bridge ABRecordRef)evaluatedObject, kABPersonImageFormatThumbnail), nil);
}
[arr addObject:(__bridge id)persona];
CFRelease(multiPhone);
CFRelease(persona);
}
}
else {
[arr addObject:evaluatedObject];
}
}
}
CFRelease(phoneNumbers);
[self.filteredContacts setObject:arr forKey:key];
RCLog(@"%i contacts for key %@", arr.count, key);
}
}
self.filteredKeys = [[self.filteredContacts allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock();
});
});
}