CFStrings and storing them into models, related topics
- by Jasconius
I have a very frustrating issue that I believe involves CFStringRef and passing them along to custom model properties.
The code is pretty messy right now as I am in a debug state, but I will try to describe the problem in words as best as I can.
I have a custom model, User, which for irrelevant reasons, I am storing CF types derived from the Address Book API into. Examples include: Name, email as NSStrings. I am simply retrieving the CFStringRef value from the AddressBook API and casting as a string, whereupon I assign to the custom model instance and then CFRelease the string.
These NSString properties are set as (nonatomic, retain).
I then store this model into an NSArray, and I use this Array as a datasource for a UITableView
When accessing the object in the cellForRowAtIndexPath, I get a memory access error.
When I do a Debug, I see that the value for this datasource array appears at first glance to be corrupted. I've seen strange values assigned to it, including just plain strings, such as one that I fed to an NSLog function in earlier in the method.
So, the thing that leads me to believe that this is Core Foundation related is that I am executing this exact same code, in the same class even, on non-Address Book data, in fact, just good old JSON parsed strings, which produce true Cocoa NSStrings, that I follow the same exact steps to create the datasource array. This code works fine.
I have a feeling that my (retain) property declaration and/or my [stringVar release] in my custom model dealloc method may be causing memory problems (since it is my understanding that you shouldn't call a Cocoa retain or release on a CF object).
Here is the code. I know some of this is super-roundabout but I was trying to make things as explicit as possible for the sake of debugging.
NSMutableArray *friendUsers = [[NSMutableArray alloc] init];
int numberOfPeople = CFArrayGetCount(people);
for (int i = 0; i < numberOfPeople; i++)
{
ABMutableMultiValueRef emails = ABRecordCopyValue(CFArrayGetValueAtIndex(people, i), kABPersonEmailProperty);
if (ABMultiValueGetCount(emails) > 0)
{
User *addressContact = [[User alloc] init];
NSString *firstName = (NSString *)ABRecordCopyValue(CFArrayGetValueAtIndex(people, i), kABPersonFirstNameProperty);
NSString *lastName = (NSString *)ABRecordCopyValue(CFArrayGetValueAtIndex(people, i), kABPersonLastNameProperty);
NSLog(@"%@ and %@", firstName, lastName);
NSString *fullName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
NSString *email = [NSString stringWithFormat:@"%@", (NSString *)ABMultiValueCopyValueAtIndex(emails, 0)];
NSLog(@"the email: %@", email);
[addressContact setName:fullName];
[addressContact setEmail:email];
[friendUsers addObject:addressContact];
[firstName release];
[lastName release];
[email release];
[addressContact release];
}
CFRelease(emails);
}
NSLog(@"friend count: %d", [friendUsers count]);
abFriends = [NSArray arrayWithArray:friendUsers];
[friendUsers release];
All of that works, every logging statement returns as expected. But when I use abFriends as a datasource, poof. Dead.
Is my approach all wrong? Any advice?