Memory leak in NSMutableArray, NSArray, NSString in iPhone SDK - iphone

In my app, I got Memory leaks in NSMutableArray, NSArray and NSString.
Here is the code.
NSString *subQuery = [NSString stringWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];
[subArray addObjectsFromArray:subArray1];
NSString *columnQuery = [NSString stringWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];
[langArray addObjectsFromArray:newArray];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:[NSString stringWithFormat:#"%#",lblshortName.text]];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[tempArray addObject:[NSString stringWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
}
else {
[tempArray addObject:#"<empty>"];
}
NSString *detail = #"_________________";
for (int j=0; j<[lableNameArray count]; j++) {
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:[NSString stringWithFormat:#"%#",[lableNameArray objectAtIndex:j]]];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
detail = [NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4];
}
}
[detailTextArray addObject:detail];
}
When I run in Instruments I got leaks in
-subArray1 in second line.
-detail (NSString) in second for loop.
And subArray and langArray are my global arrays.
If I remove mutableCopy from NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; and NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; then subArray and langArray doesnot retain values.
How to avoid memory leak in this code?

Olease try this one, in above code you are creating two many objects that belong to autorelease pool here is one version where I tried to handle release of those string variables.
Second this is that the leak of detail is because you are de-referencing it many times in your code. And for subArray1 please see the comment
NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
// please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
[subArray addObjectsFromArray:subArray1];
[subQuery release];
NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
[langArray addObjectsFromArray:newArray];
[columnQuery relese];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:#"%#",lblshortName.text]];
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
[tempKey release];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
[tempArray addObject:tempString];
[tempString release];
}
else {
[tempArray addObject:#"<empty>"];
}
NSMutableString *detail = nil;
for (int j=0; j<[lableNameArray count]; j++)
{
detail = [[ NSMutableString alloc]initWithString:#"_________________"];
NSMutableString *key = [[NSMutableString alloc]initWithFormat:#"%#",[lableNameArray objectAtIndex:j]];
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key];
[key release];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail setString:[NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
}
[detailTextArray addObject:detail];
[detail release];
}
}
[subArray1 release];
[newArray release];
UPDATE : Please do read comments in the code and reply back so that things could be improved.
NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
//*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
[subArray addObjectsFromArray:subArray1];
[subQuery release];
NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
//*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
[langArray addObjectsFromArray:newArray];
[columnQuery relese];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:#"%#",lblshortName.text]];
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
[tempKey release];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
[tempArray addObject:tempString];
[tempString release];
}
else {
[tempArray addObject:#"<empty>"];
}
NSMutableString *detail = [[ NSMutableString alloc]initWithString:#"_________________"];
for (int j=0; j<[lableNameArray count]; j++)
{
NSMutableString *key = [[NSMutableString alloc]initWithFormat:#"%#",[lableNameArray objectAtIndex:j]];
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; //also here if you note you are using subArray1 not subArray?
[key release];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail setString:[NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
break;//I am not sure why you are checking this condition but assume that you want to get NOT NULL VALUE and add it to array?
}
}
[detailTextArray addObject:detail];
[detail release];
}
[subArray1 release];
[newArray release];
UPDATE 2:
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail appendFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
}
Thanks,

Not sure what is causing the memory leak, but this may help. This is a more direct way of copying the arrays, and may result in avoiding the leak:
NSArray *langArray =[[NSArray alloc] initWithArray: [self returnExecuteQuery:columnQuery] copyItems: YES];
This basically makes a one-level deep copy of the array returned by returnExecuteQuery. You can read about it in more detail in Collections Programming Topics.
I'm not sure how mutableCopy works and that may have something to do with the leak. If it copies the objects in the old array & then adds them to the new array, they may enter the array with a retain count of 2 (1 from the copy, and 1 from being added to an array.) It doesn't make much sense that it should work this way. But, if it does, that could account for the leak.

You could start by releasing your tempArray once done with it (after the loops).
Often, the higher levels leaks are hidden in the flood of lower level ones (ie a container leaking causes all its content to be leaked as well), which might be the case for your string.
Using mutableCopy] autorelease]; is fine by the way.

Related

Display NSMutableArray in UIlabel in xcode

I have to display NSmutableArray data in UIlabel .But only the last index text is getting added .Here is my code
marray:
(
{
ID=1;
}
{
ID="2"
}
)
for(int i=0;i<[marray count];i++)
{
eventName=[[arr2 objectAtIndex:i]objectForKey:#"Code"];
label.text=[NSString stringWithFormat:#"ID :%#",eventName ];
}
I have to display these ID's in UIlabel with text as : 1 , 2
How can I do it?
you can append string to NSString object than use that object in label like bellow
NSMutableString *lblstr=#"ID :";
for (int i=0; i<[marray count]; i++) {
eventName=[[arr2 objectAtIndex:i]objectForKey:#"Code"];
[lblstr appendString:[NSString stringWithFormat:#"%#",eventName ]];
}
label.text=lblstr;
You are running a for loop which will continue executing till its last increment . So the last value in the array would be displayed. So what you can do is that you can add a timer instead of a for loop that is if you want to show your NSmutableArray as changing in the UILabel.
EDIT:
-(IBAction) rotate3
{
NSString *number = [self.dayArray description];
NSArray *array = [[NSArray alloc] initWithObjects: #"0", #"1", #"2", #"3", #"4", #"5" ,#"6", #"7", #"8",#"9",#"10",#"11",#"12",#"13", #"14", #"15", #"16", #"17", #"18", #"19",nil];
numberCount++;
timer=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(rotate3 )userInfo:nil repeats:YES];
self.dayArray = array;
[array release];
label.text = [NSString stringWithFormat:#"Day %# ", number];
}
Also check these links How to update UILabel programmatically in iOS and How to display an NSArray in a UILabel and use timer
Try the below Code.
NSString *temp=#"";
for(int i=0;i<[marray count];i++)
{
//eventName=[[arr2 objectAtIndex:i]objectForKey:#"Code"];
temp=[temp stringByAppendingString:[[arr2 objectAtIndex:i]objectForKey:#"Code"]];
temp=[temp stringByAppendingString:#" ,"];
}
temp = [temp substringToIndex:[temp length]-1];
label.text=[NSString stringWithFormat:#"ID :%#",temp ];
NSMutableString *str = [[NSMutableString alloc] init];
for(int i=0;i<[marray count];i++)
{
NSString *temp = [NSString stringWithFormat:#"%d - %#\n",i+1, [[arr2 objectAtIndex:i]objectForKey:#"Code"]];
[str appendString:[NSString stringWithFormat:#"%#",temp]];
//sleep(0.05); //Remove comment this line may help ! **Tricky Line**
}
label.text = str;
[str release];
You may create an array of objects (indexes) and use componentsJoinedByString:
NSString* str = [array componentsJoindeByString: #", "];
Or using your code, replacing
label.text=[NSString stringWithFormat:#"ID :%#",eventName ];
with:
label.text=[label.text stringByAppendingFormat:#", %#", eventName];

how can print array json values into uitableview in iphone

JSON format code looks like this:
{
"rates": {
"amc": "201",
"hyd": "500.50",
"guj": "200.10",
"afgd": "400"
}
}
After parsing JSON values the above code array returns:
array = [values valueForKey:#"rates"];
which array return
{
amc = "201";
hyd = "500.50";
guj = "200.10";
afgd = "400";
...........etc
}
But i want to print in UITableView look amc:201
How can i do this?
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
self.responseData = nil;
values = [responseString JSONValue];
array = [[NSMutableArray alloc] init];
NSMutableArray *arrTitle = [[NSMutableArray alloc] init];
NSMutableArray *arrValues = [[NSMutableArray alloc] init];
array =[values valueForKey:#"rates"];
NSLog(#"array values:--> %#",array);
// NSLog(#"values:--> %#",values);
// NSLog(#"Particular values:--> %#",[[values valueForKey:#"rates"] valueForKey:#"AED"]);
tempDict1 = (NSMutableDictionary *)array;
NSArray *arr;// =[[NSArray alloc]init];
arr = [[tempDict1 valueForKey:#"rates"] componentsSeparatedByString:#";"];
NSLog(#"arr-->%#",arr);
NSString *subStar = #"=";
[arrTitle removeAllObjects];
[arrValues removeAllObjects];
for (int i=0; i<[arr count]-1; i++)
{
[arrTitle addObject:[[arr objectAtIndex:i] substringToIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:subStar])-1]];
[arrValues addObject:[[arr objectAtIndex:i] substringFromIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:subStar])]];
NSLog(#"arrTitle is:--> %#",arrTitle);
}
tempDict1 = (NSMutableDictionary*)[array objectAtIndex:0];
array = [values valueForKey:#"rates"];
NSLog(#"tempDict--%#",[tempDict1 objectForKey:#"AED"]);
[array retain];
[tbl_withData reloadData];
}
try:
NSMutableArray * array2=[[NSMutableArray alloc]init];
[array addObject: [[array objectAtIndex:0] objectForKey:#"amc"]];
[array addObject: [[array objectAtIndex:0] objectForKey:#"hyd"]];
[array addObject: [[array objectAtIndex:0] objectForKey:#"guj"]];
[array addObject: [[array objectAtIndex:0] objectForKey:#"afgd"]];
now put array2 values in your table cell.
like:
cell.text=[array2 objectAtIndex:indexPath.row];
try this:-
NSDictionary *dict =[values valueForKey:#"rates"];
NSString *str=[dict valueForKey:#"amc"];
You need to do this:-
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
self.responseData = nil;
values = [responseString JSONValue];
NSMutableArray *arrTitle = [[NSMutableArray alloc] init];
NSMutableArray *arrValues = [[NSMutableArray alloc] init];
NSDictionary *dict =[values valueForKey:#"rates"];
NSString *str=[dict valueForKey:#"amc"];
rest you can do according to your requirements.
Return type for [values valueForKey:#"rates"] is a dictionary not array of values.
NSDictionary *dict = [values valueForKey:#"rates"];
Now you can refer get values within dictionary using objectForKey
Or else if you want to store in array.
NSMutableArray *array = [NSMutableArray array];
for (NSString *key in [dict allKeys])
{
array = [dict objectForKey:key];
}
So finally array has all the values within dictionary.
// returns no of rows
-(NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section
{
return [array count];
}
// contents of row will be
-(UITableViewCell*) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
static NSString *CellIdentifier = #"test";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSString *value = [self. array objectAtIndex:indexPath.row];
cell.textLabel.text = value;
return cell;
}

My app crashes with "Program received EXC_BAD_ACCESS" error iphone

When my app launches from BACKGROUND , I am running a new thread to get AddresssBook data using notification center. Here is my code which shows how I call the method
-(void)appLaunchedFromBackground:(NSNotification *) notification {
// NSThread *backgroundThread; is my ivar
backgroundThread = [[NSThread alloc]initWithTarget:self selector:#selector(getUpdatedAddressBookData) object:nil];
[backgroundThread start];
}
-(void)getUpdatedAddressBookData {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AddressBook *addBook = [[AddressBook alloc]init];
[addBook fetchAddressBookDataInBackground];
[addBook release];
[pool drain];
}
Here is my code for fetchAddressBookDataInBackground method
-(void)fetchAddressBookDataInBackground {
if (self.tempArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.tempArray = temp;
[temp release];
}
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *tempPeople = [[NSArray alloc]init];
tempPeople = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
APP_DELGATE.people = [NSArray arrayWithArray:tempPeople];
int peoCount = [APP_DELGATE.people count];
for (int i=0; i<peoCount; i++) {
ABRecordRef record = [APP_DELGATE.people objectAtIndex:i];
NSNumber *recordId = [NSNumber numberWithInteger:ABRecordGetRecordID(record)];
// Get fname, lname, company
NSString *fnm = (NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty) ;
NSString *lnm = (NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty) ;
NSString *comp = (NSString*)ABRecordCopyValue(record,kABPersonOrganizationProperty);
// Get Ph no
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(record, kABPersonPhoneProperty);
NSArray *tempPhNos = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
NSArray* phoneNumbers = [self getPhoneNoWithoutSymbols:tempPhNos];
NSString *strPhoneNos = [self getStringRepresentaionFromArray:phoneNumbers];
// Get emails
ABMultiValueRef emailProperty = ABRecordCopyValue(record, kABPersonEmailProperty);
NSArray* emails = (NSArray*)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSString *strEmails = [self getStringRepresentaionFromArray:emails];
// Get URL
ABMultiValueRef urlProperty = ABRecordCopyValue(record, kABPersonURLProperty);
NSArray* urls = (NSArray*)ABMultiValueCopyArrayOfAllValues(urlProperty);
NSString *strURLs = [self getStringRepresentaionFromArray:urls];
// Get Address
ABMultiValueRef address=ABRecordCopyValue(record, kABPersonAddressProperty);
CFDictionaryRef dic=nil;
NSMutableArray *addressArray = [[NSMutableArray alloc]init];
for (int index=0; index<ABMultiValueGetCount(address); index++) {
dic=ABMultiValueCopyValueAtIndex(address, index);
NSString* labelName=(NSString*)ABMultiValueCopyLabelAtIndex(address, index);
if (labelName) {
NSString *street =(NSString*) CFDictionaryGetValue(dic, kABPersonAddressStreetKey);
NSString *city= (NSString*)CFDictionaryGetValue(dic, kABPersonAddressCityKey) ;
NSString *state= CFDictionaryGetValue(dic, kABPersonAddressStateKey);
NSString *country=CFDictionaryGetValue(dic, kABPersonAddressCountryKey);
NSString *zipcode=CFDictionaryGetValue(dic, kABPersonAddressZIPKey);
NSString *addressDetails=#"";
if (street) {
addressDetails=[NSString stringWithFormat:#"%# ",street];
}
if (city) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,city];
}
if (state) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,state];
}
if (country) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,country];
}
if (zipcode) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,zipcode];
}
[addressArray addObject:addressDetails];
}
[labelName release];
CFRelease(dic);
}
NSString *strAddress = [self getStringRepresentaionFromArray:addressArray];
// Get Notes
NSString *noteString=(NSString *)ABRecordCopyValue(record, kABPersonNoteProperty);
// Get Birthdate
NSDate *birthDate=(NSDate*)ABRecordCopyValue(record, kABPersonBirthdayProperty) ;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM dd yyyy"];
NSString *birthdateString = [formatter stringFromDate:birthDate];
[formatter release];
// Get user image
UIImage *image = nil;
if( ABPersonHasImageData( record ) ) {
NSData *imageData = (NSData*)ABPersonCopyImageData(record);
image = [UIImage imageWithData:imageData];
[imageData release];
}
NSString *fullName = [NSString stringWithFormat:#"%# %#",fnm,lnm];
// Create User object & add it to array
User *user = [[User alloc]initUserWithUniqID:recordId.intValue FirstName:fnm lastName:lnm compositeName:fullName company:comp phoneNumbers:strPhoneNos emails:strEmails urls:strURLs address:strAddress notes:noteString dob:birthdateString userImage:image];
[self.tempArray addObject:user];
CFRelease(phoneNumberProperty);
[tempPhNos release];
CFRelease(emailProperty);
[emails release];
CFRelease(urlProperty);
[urls release];
CFRelease(address);
[addressArray release];
[birthDate release];
[comp release];
[noteString release];
[lnm release];
[fnm release];
[user release];
}
[tempPeople release];
CFRelease(addressBook);
addressBook = nil;
self.tempArray = [NSMutableArray arrayWithArray:[self.tempArray sortedArrayUsingSelector:#selector(compare:)]];
APP_DELGATE.allUsersArray = self.tempArray;
NSDictionary *dic = [NSDictionary dictionaryWithObject:self.tempArray forKey:BATCH_DONE_KEY];
[[NSNotificationCenter defaultCenter] postNotificationName:BACKGROUND_WORK_DONE_NOTIFICATION object:self userInfo:dic];
}
-(NSMutableArray*)getPhoneNoWithoutSymbols:(NSArray*)array {
if (self.phNoArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.phNoArray = temp;
[temp release];
}
[self.phNoArray removeAllObjects];
for (NSString *str in array) {
[self.phNoArray addObject:[self getPhNo:str]];
}
return self.phNoArray;
}
-(NSString*)getPhNo:(NSString*)str {
NSString *str0 = [str stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *str1 = [str0 stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *str2 = [str1 stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *str3 = [str2 stringByReplacingOccurrencesOfString:#"-" withString:#""];
return str3;
}
-(NSString*)getStringRepresentaionFromArray:(NSArray*)array {
return [array componentsJoinedByString:DELIMITER_SYMBOL];
}
But my app crashes with "Program received EXC_BAD_ACCESS" error at any line where I am using "ABRecordCopyValue" function . What I am missing? I am not getting whats wrong in my code?
I tried setting NSZombieEnabled = YES , but its not showing any message. Just saying "Program received EXC_BAD_ACCESS" at any line using ABRecordCopyValue function & in console I see (gdb) thats it.
Any knid of help is highly appreciated. Thanks.

Potential leak of an object allocated in iphone

when i am analyze my project following code gives me leakage warning. is there any way to solve my memory leakage problem ?
warning :
Potential leak of an object allocated on line 38 and stored into 'addressBook'
Bellow is my code.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
m_tableDataArray = [[[NSMutableArray alloc] init]autorelease];
NSMutableArray *listDate = [[[NSMutableArray alloc] init]autorelease];
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *addresses = (NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);
NSInteger addressesCount = [addresses count];
for (int i = 0; i < addressesCount; i++) {
ABRecordRef record = [addresses objectAtIndex:i];
NSString *firstName = (NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty);
NSString *lastName = (NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty);
if(firstName != nil && lastName != nil){
NSString *contactFirstLast = [NSString stringWithFormat: #"%# %#", firstName, lastName];
[listDate addObject:contactFirstLast];
}
[firstName release];
[lastName release];
}
m_tableDataArray = [[NSArray arrayWithArray:listDate] retain];
[addresses release];
addresses = nil;
[m_mainTable reloadData];
}
Thanks in adv...
Once you have finished using addressBook you need to release it using:
CFRelease(addressBook);
This should probably be placed at the end of your viewWillAppear: method.
Updated: There are a few unnecessary arrays and steps in your version of viewWillAppear:. I have cleaned it up a bit and fixed a potential memory leak.
Note: I haven't actually run this so double-check that it works correctly.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// I assume m_tableDataArray is an instance variable. If so, if the
// view appears multiple times it will result in a leak unless we
// release pre-existing instances first.
[m_tableDataArray release], m_tableDataArray = nil;
m_tableDataArray = [[NSMutableArray alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *addresses = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
for (ABRecordRef record in addresses) {
NSString *firstName = (NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty);
NSString *lastName = (NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty);
if(firstName != nil && lastName != nil){
NSString *contactFirstLast = [NSString stringWithFormat: #"%# %#", firstName, lastName];
[m_tableDataArray addObject:contactFirstLast];
}
[firstName release];
[lastName release];
}
[addresses release], addresses = nil;
CFRelease(addressBook);
[m_mainTable reloadData];
}

UISearchBar - search a NSDictionary of Arrays of Objects

I'm trying to insert a search bar in a tableview, that is loaded with information from a NSDictionary of Arrays. Each Array holds and object. Each object has several properties, such as Name or Address.
I've implemented the methods of NSSearchBar, but the code corresponding to the search it self, that i have working on another project where the Arrays have strings only, is not working, and I can't get to thr problem.
Here's the code:
'indiceLateral' is a Array with the alphabet;
'partners' is a NSDictionary;
'RLPartnersClass' is my class of Partners, each one with the properties (name, address, ...).
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.indiceLateral) {
NSMutableArray *array = [partners valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array) {
if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.indiceLateral removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[theTable reloadData];
}
Can anyone help me please?
Thanks,
Rui Lopes
I've done it.
Example:
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableDictionary *finalDict = [NSMutableDictionary new];
NSString *currentLetter = [[NSString alloc] init];
for (int i=0; i<[indiceLateral count]; i++) {
NSMutableArray *elementsToDict = [[[NSMutableArray alloc] init] autorelease];
currentLetter = [indiceLateral objectAtIndex:i];
NSArray *partnersForKey = [[NSArray alloc] initWithArray:[partnersCopy objectForKey:[indiceLateral objectAtIndex:i]]];
for (int j=0; j<[partnersForKey count]; j++) {
RLNames *partnerInKey = [partnersForKey objectAtIndex:j];
NSRange titleResultsRange = [partnerInKey.clientName rangeOfString:searchTerm options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0){
NSLog(#"found: %#", partnerInKey.clienteCity
[elementsToDict addObject:partnerInKey];
}
}
[finalDict setValue:elementsToDict forKey:currentLetter];
}
NSMutableDictionary *finalResultDict = [finalDict mutableDeepCopy];
self.partners = finalResultDict;
[finalResultDict release];
[theTable reloadData];
}