NSString with NSmutablearray Memory leaks - objective-c

When I run with Instrument the below code gets memory leaking.
Here I have declared all NSMutablearrays are as properties.
I have made comments here where exactly memory is leaking.
-(void)getholidays
{
if (idarray!=nil) {
[idarray release];
idarray=nil;
}
idarray=[[NSMutableArray alloc]init];
if (Countryarray!=nil) {
[Countryarray release];
Countryarray=nil;
}
Countryarray =[[NSMutableArray alloc] init];
if (Holidaynamearray!=nil) {
[Holidaynamearray release];
Holidaynamearray=nil;
}
Holidaynamearray =[[NSMutableArray alloc] init];
if (Datearray!=nil) {
[Datearray release];
Datearray=nil;
}Datearray =[[NSMutableArray alloc] init];
if (Dayarray!=nil) {
[Dayarray release];
Dayarray=nil;
}Dayarray =[[NSMutableArray alloc] init];
if (Favoritearray!=nil) {
[Favoritearray release];
Favoritearray=nil;
}
Favoritearray =[[NSMutableArray alloc] init];
NSString *destinationPath = [self getdestinationPath];
const char *dbpath = [destinationPath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL;
NSDate *today = [NSDate date];
NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"MMMM-dd-yyyy"];
NSString *Todaystrng = [formatter stringFromDate:today];
NSLog(#"today date %#",Todaystrng);
querySQL=[NSString stringWithFormat:#"SELECT * FROM Holiday_Table WHERE CountryName in (SELECT Country_Name from Country WHERE Country_Selected =1) ORDER BY Date ASC "];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"success");
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *idstringfromdb=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
NSString *countrynamestringfromdb=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
NSString *holidaynamestringfromdb=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
NSString *datestringfromdb=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
//Below line gets leaking
NSString *daystringfromdb=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
//Belowline gets leaking
NSString *favoritestringfromdb=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];
[idarray addObject:idstringfromdb];
[idstringfromdb release];
idstringfromdb=nil;
[Countryarray addObject:countrynamestringfromdb];
[countrynamestringfromdb release];
countrynamestringfromdb=nil;
[Holidaynamearray addObject:holidaynamestringfromdb];
[holidaynamestringfromdb release];
holidaynamestringfromdb=nil;
[Datearray addObject:datestringfromdb];
[datestringfromdb release];
datestringfromdb=nil;
[Dayarray addObject:daystringfromdb];
[daystringfromdb release];
daystringfromdb=nil;
[Favoritearray addObject:favoritestringfromdb];
[favoritestringfromdb release];
favoritestringfromdb=nil;
}
}
sqlite3_close(database);
}
sqlite3_finalize(statement);
}
Thanks.

You are closing the database before you finalize your statement. This means that the resources returned by your statement are not properly freed. Here is what the documentation has to say about sqlite3_close.
Applications must finalize all prepared statements and close all BLOB
handles associated with the sqlite3 object prior to attempting to
close the object. If sqlite3_close() is called on a database
connection that still has outstanding prepared statements or BLOB
handles, then it returns SQLITE_BUSY.

Related

two PickerViews of a single Sqlite3 Database

I must be doing something wrong here. My SQLite database is working. However, I cannot seem to populate the tname into a picker view while the picked populates three text fields tname, latitude, and longitude.
Info: Two picker views that are independent from each other, they both read the same sqlite db.
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *array1;
sqlite3 *towerDB;
NSString *dbPathString;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//UIPickerView *pickerview1;
//array1 = [[NSMutableArray alloc]init];
[[self pickerview1]setDelegate:self];
[[self pickerview1]setDataSource:self];
[self displayTower];
}
- (void)displayTower
{
array1 = [[NSMutableArray alloc] init];
sqlite3_stmt *statement;
if (sqlite3_open([dbPathString UTF8String], &towerDB)==SQLITE_OK) {
[array1 removeAllObjects];
NSString *querySql = [NSString stringWithFormat:#"SELECT * FROM TOWERS"];
const char* query_sql = [querySql UTF8String];
// sqlite3_clear_bindings(statement);
// sqlite3_reset(statement);
if (sqlite3_prepare(towerDB, query_sql, -1, &statement, NULL)==SQLITE_OK) // NOT OK
//This Code works in a TableView!!
//Will NOT work in a PickerView
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
NSString *tname = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSString *latitude = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *longitude = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
// NSString *ds2 = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
NSString *PickerTower = [[NSString alloc] initWithFormat:#"%#", tname];
NSString *lat1 = [[NSString alloc] initWithFormat:#"%#", latitude];
NSString *long1 = [[NSString alloc] initWithFormat:#"%#", longitude];
NSArray *array = [[NSArray alloc] initWithObjects:PickerTower, nil];
[array1 addObject:array];
NSLog(#"Lat/Long %# / %#", lat1, long1);
}
}
}
}
#pragma mark Picker Data Source Methods
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
//ONE Colume
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
//data view how many items?
return [array1 count];
// return [_array2 count];
}
#pragma mark Picker Delegate Methods
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [array1 objectAtIndex:row];
//return [self->array1 objectAtIndex:row];
// array1 = [[NSMutableArray alloc] init];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
long select = row;
NSLog(#"PickerView %ld", select);
}
#end
You have to changed this code in the method name displayTower and code lines -
[array1 addObject:array];
NSLog(#"Lat/Long %# / %#", lat1, long1);
with -
[array1 addObject:array];
NSLog(#"Lat/Long %# / %#", lat1, long1);
[[self pickerview1] reloadAllComponents];
may be it will help you, or feel free.

Getting repeated values when I try to add a dictionary to an array in a loop

This is my code for my test app where I want to show users on the next view controller but when I run and try to retrieve the values it is giving me repeated values. I have used NSMutableDictionary and NSMutableArray.
#import "DBManager.h"
static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;
#implementation DBManager
-(void) getsaveData:(NSString *)Username
{
const char *dbpath = [newFileAtPath UTF8String];
NSMutableArray *userArray = [[NSMutableArray alloc]init];
if (sqlite3_open(dbpath, &database)==SQLITE_OK) {
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSString *getSQL = [NSString stringWithFormat:#"SELECT * FROM USERS WHERE USERNAME != \"%#\"",Username];
const char *retrievestmt = [getSQL UTF8String];
if(sqlite3_prepare_v2(database, retrievestmt, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement)==SQLITE_ROW)//in this while loop i am getting repeated values
{
NSString *User_ID = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
[userInfo setObject:User_ID forKey:#"ID"];
//[userArray addObject:User_ID];
NSString *User_Email = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
[userInfo setObject:User_Email forKey:#"Email"];
//[userArray addObject:User_Email];
NSString *Password = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
[userInfo setObject:Password forKey:#"Email"];
//[userArray addObject:Password];
NSString *User_name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
[userInfo setObject:User_name forKey:#"Username"];
//[userArray addObject:User_name];
NSString *User_Avatar = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
[userInfo setObject:User_Avatar forKey:#"Avatar"];
//[userArray addObject:User_Avatar];
[userArray addObject:userInfo];
NSLog(#"userArray %#",userArray);
}
sqlite3_reset(statement);
}
}
}
#end
In the while loop I am geeting the error.
I tried multiple times with multiple solutions please help me fix this.
The problem is simple - you are incorrectly reusing the userInfo dictionary. You need to create a new instance in each loop iteration.
Move the line:
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
to just after the while loop line.
You also have many other issues with your code:
You never close the database.
You never finalize the prepared statement.
You needlessly reset the prepared statement.
You have insufficient error checking/logging.
You are not using standard naming conventions.
You are not using standard whitespacing which makes your code harder to read.
You don't use consistent curly brace placement. Pick a style and use it everywhere.
You are using static variables when you should not be.
Never build SQL statements using stringWithFormat:. Properly bind values to the query.
Never use SELECT * in a query. Explicitly list out the columns to ensure you get consistent and expected column values.
Here's is your code updated for these issues:
#import "DBManager.h"
static DBManager *sharedInstance = nil;
#implementation DBManager
- (void)getsaveData:(NSString *)username {
const char *dbpath = [newFileAtPath UTF8String];
NSMutableArray *userArray = [[NSMutableArray alloc] init];
sqlite3 *database;
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
const char *retrievestmt = "SELECT USER_ID, USER_EMAIL, PASSWORD, USER_NAME, USER_AVATAR FROM USERS WHERE USERNAME != ?"; // replace * with actual column names
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, retrievestmt, -1, &statement, NULL) == SQLITE_OK) {
sqlite3_bind_text(statement, 1, [username UTF8String], -1, SQLITE_TRANSIENT);
while (sqlite3_step(statement) == SQLITE_ROW) {
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSString *userID = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
userInfo[#"ID"] = userID;
NSString *userEmail = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
userInfo[#"Email"] = userEmail;
NSString *password = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
userInfo[#"Password"] = password;
NSString *username = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
userInfo[#"Username"] = username;
NSString *userAvatar = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
userInfo[#"Avatar"] = userAvatar;
[userArray addObject:userInfo];
}
sqlite3_finalize(statement);
NSLog(#"userArray %#",userArray);
} else {
NSLog(#"Unable to prepare the statement at %s: %s", retrievestmt, sqlite3_errmsg(database));
}
sqlite3_close(database);
} else {
NSLog(#"Unable to open the database at %#: %s", dbpath, sqlite3_errmsg(database));
}
}
#end

Objective-C / ALAssetslibrary - How can i change my method to work synchronously

I have implemented a method that retrieve correctly the informations about images using the Alassetslibrary. As you know, it works asynchronously but in my case i need that it works synchronously. I have only to read the informations about images and return to the method. My application as only one view that doesn't need a refresh. How can i modify my method? At the moment the line "return xmlList;" result always null, but i know that the assets are correctly read in the block because i have used a NSlog.
-(NSString *) getPhotos{
NSMutableArray *idList = [[NSMutableArray alloc] init];
NSMutableArray *widthList = [[NSMutableArray alloc] init];
NSMutableArray *heightList = [[NSMutableArray alloc] init];
NSMutableArray *orientationList = [[NSMutableArray alloc] init];
NSMutableArray *dateList = [[NSMutableArray alloc] init];
__block XMLWriter* xmlWriter = [[XMLWriter alloc]init];
__block NSString *xmlList;
__block NSString *test;
__block ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
__block NSString *description = [[NSString alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
if (asset){
NSString *description = [asset description];
NSRange first = [description rangeOfString:#"URLs:"];
NSRange second = [description rangeOfString:#"?id="];
NSString *path = [description substringWithRange: NSMakeRange(first.location + first.length, second.location - (first.location + first.length))];
[idList addObject:path];
NSDictionary *data = [[asset defaultRepresentation] metadata];
NSNumber *width = [[[asset defaultRepresentation] metadata] objectForKey:#"PixelWidth"];
NSString *widthString = [NSString stringWithFormat:#"%#", width];
[widthList addObject:widthString];
NSNumber *height = [[[asset defaultRepresentation] metadata] objectForKey:#"PixelHeight"];
NSString *heightString = [NSString stringWithFormat:#"%#", height];
[heightList addObject:heightString];
NSNumber *orientation = [[[asset defaultRepresentation] metadata] objectForKey:#"Orientation"];
NSString *orientationString = [NSString stringWithFormat:#"%#", orientation];
if(orientationString != NULL){
[orientationList addObject:orientationString];
} else {
NSString *noOrientation = [[NSString alloc] init];
noOrientation = #"No orientation avaiable";
[dateList addObject:noOrientation];
}
NSString *dateString = [[[asset defaultRepresentation] metadata] objectForKey:#"DateTime"];
if(dateString != NULL){
[dateList addObject:dateString];
} else {
NSString *noDate = [[NSString alloc] init];
noDate = #"No date avaiable";
[dateList addObject:noDate];
}
}
}];
}
if (group == nil){
[xmlWriter writeStartDocumentWithEncodingAndVersion:#"UTF-8" version:#"1.0"];
[xmlWriter writeStartElement:#"Data"];
int i = 0;
for(i = 0; i<=[idList count]-1; i++){
[xmlWriter writeStartElement:#"Photo"];
[xmlWriter writeAttribute:#"Id" value:[idList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Width" value:[widthList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Height" value:[heightList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Orientation" value:[orientationList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Date" value:[dateList objectAtIndex:i]];
[xmlWriter writeEndElement:#"Photo"];
}
[xmlWriter writeEndElement:#"Data"];
[xmlWriter writeEndDocument];
xmlList = [xmlWriter toString];
}
} failureBlock:^(NSError *error) {
NSLog(#"error enumerating AssetLibrary groups %#\n", error);
}];
return xmlList;
}
Ok at the end i have resolve my problem. I have used the NSConditionLock Class. Here there is the updated code:
-(NSString *) getPhotos{
enum { WDASSETURL_PENDINGREADS = 1, WDASSETURL_ALLFINISHED = 0};
NSMutableArray *idList = [[NSMutableArray alloc] init];
NSMutableArray *widthList = [[NSMutableArray alloc] init];
NSMutableArray *heightList = [[NSMutableArray alloc] init];
NSMutableArray *orientationList = [[NSMutableArray alloc] init];
NSMutableArray *dateList = [[NSMutableArray alloc] init];
__block XMLWriter* xmlWriter = [[XMLWriter alloc]init];
__block NSString *xmlList;
__block NSString *test;
__block NSConditionLock * assetsReadLock = [[NSConditionLock alloc] initWithCondition:WDASSETURL_PENDINGREADS];
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__block ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
__block NSString *description = [[NSString alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
if (asset){
NSString *description = [asset description];
NSRange first = [description rangeOfString:#"URLs:"];
NSRange second = [description rangeOfString:#"?id="];
NSString *path = [description substringWithRange: NSMakeRange(first.location + first.length, second.location - (first.location + first.length))];
[idList addObject:path];
NSDictionary *data = [[asset defaultRepresentation] metadata];
NSNumber *width = [[[asset defaultRepresentation] metadata] objectForKey:#"PixelWidth"];
NSString *widthString = [NSString stringWithFormat:#"%#", width];
[widthList addObject:widthString];
NSNumber *height = [[[asset defaultRepresentation] metadata] objectForKey:#"PixelHeight"];
NSString *heightString = [NSString stringWithFormat:#"%#", height];
[heightList addObject:heightString];
NSNumber *orientation = [[[asset defaultRepresentation] metadata] objectForKey:#"Orientation"];
NSString *orientationString = [NSString stringWithFormat:#"%#", orientation];
if(orientationString != NULL){
[orientationList addObject:orientationString];
} else {
NSString *noOrientation = [[NSString alloc] init];
noOrientation = #"No orientation avaiable";
[dateList addObject:noOrientation];
}
NSString *dateString = [[[asset defaultRepresentation] metadata] objectForKey:#"DateTime"];
if(dateString != NULL){
[dateList addObject:dateString];
} else {
NSString *noDate = [[NSString alloc] init];
noDate = #"No date avaiable";
[dateList addObject:noDate];
}
}
}];
}
if (group == nil){
[xmlWriter writeStartDocumentWithEncodingAndVersion:#"UTF-8" version:#"1.0"];
[xmlWriter writeStartElement:#"Data"];
int i = 0;
for(i = 0; i<=[idList count]-1; i++){
[xmlWriter writeStartElement:#"Photo"];
[xmlWriter writeAttribute:#"Id" value:[idList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Width" value:[widthList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Height" value:[heightList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Orientation" value:[orientationList objectAtIndex:i]];
[xmlWriter writeAttribute:#"Date" value:[dateList objectAtIndex:i]];
[xmlWriter writeEndElement:#"Photo"];
}
[xmlWriter writeEndElement:#"Data"];
[xmlWriter writeEndDocument];
xmlList = [xmlWriter toString];
[assetsReadLock lock];
[assetsReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
}
} failureBlock:^(NSError *error) {
NSLog(#"error enumerating AssetLibrary groups %#\n", error);
[assetsReadLock lock];
[assetsReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
}];
});
[assetsReadLock lockWhenCondition:WDASSETURL_ALLFINISHED];
[assetsReadLock unlock];
NSLog(#"XML: %#", xmlList);
return xmlList;
}

How to get data to write to a text file?

Here is the method that I'm using for a console output. How can I output to a text file?
#implementation GetMoves
- (id)initWithDevice:(Device *)device{
if(self = [super init]){
_device = device;
}
return self;
}
- (void)Render{
[super ClearConsole];
printf("MOVES INFO\n");
printf("==================================\n");
NSArray* data = [_device GetData:NULL];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
if(data != nil){
for(int i = 0; i < data.count; i++){
DataPoint* current = [data objectAtIndex:i];
NSMutableString* output = [[NSMutableString alloc] init];
[output appendFormat:#"%d",(i+1)];
[output appendString:#" - "];
[output appendString:[dateFormatter stringFromDate:current.RecordedAt]];
[output appendString:#" - "];
[output appendFormat:#"%d",current.StepCount];
printf("%s\n", [output UTF8String]);
}
}
else
printf("No new data found on device.\n");
printf("\n");
printf("==================================\n");
printf("\n");
printf("Press ENTER to continue.");
fgetc(stdin);
}
#end
You can simply write as :
NSString *path = [#"~" stringByExpandingTildeInPath] ;
//change your path here
path=[path stringByAppendingString:#"/Documents/*REPORTS/"];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/TWCodeFile.txt",path];
//create content - four lines of text
NSString *content = #"The content of file, can be more by appending string.";
//save content to the documents directory
[content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];

Memory Leaks in UIPickerView using sqlite

I'm adding self.notes array to a UIPickerView. This is how I'm setting the array:
NSMutableArray *notesArray = [[NSMutableArray alloc] init];
[notesArray addObject:#"-"];
[notesArray addObjectsFromArray:[dbManager getTableValues:#"Notes"]];
self.notes = notesArray;
[notesArray release];
The info for the UIPickerView is taken from the database in this method:
-(NSMutableArray *)getTableValues:(NSString *)table
{
NSMutableArray *valuesArray = [[NSMutableArray alloc] init];
if (sqlite3_open([self.databasePath UTF8String], &database) != SQLITE_OK)
{
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
else
{
NSString *query = [[NSString alloc] initWithFormat:#"SELECT value FROM %#", table];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW) {
NSString *value =[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
[valuesArray addObject:value];
[value release];
}
sqlite3_reset(statement);
}
[query release];
sqlite3_finalize(statement);
sqlite3_close(database);
}
return valuesArray;
}
But I keep getting memory leaks in Instruments for these lines:
NSMutableArray *valuesArray = [[NSMutableArray alloc] init];
and
[valuesArray addObject:value];
What am I doing wrong here?
Thanks for your help!
Instead of NSMutableArray *valuesArray = [[NSMutableArray alloc] init]; use this line:
NSMutableArray *valuesArray = [NSMutableArray array];
As for the [valuesArray addObject:value]; leak, change your code to this:
[valuesArray addObject:value];
value = nil;
You are returning valuesArray from the getTableValues which is allocated but not released. You can not release it in the method as the caller still needs it. The correct way is to autorelease it.
return [valuesArray autorelease];
And also you don't need to release value string after adding it to valuesArray as it is created with a convenient constructor.