Search code examples
iosobjective-cxcodesqlitensfilemanager

When writing to text file (appending) the last value I write replaces all previous values


I'm trying to reproduce my SQLite3 table as a .csv file that is saved into the phones documents.

In order to do this I have attempted to append a new line to the end of the file, each time an object is found in my array, this works - however it seems to reproduce the last line over and over again for the exact number of rows in my sql table.

Here is the SQLite Select query:

    NSMutableArray *allGPS = [[NSMutableArray alloc] init];
    GPS *gps = [[GPS alloc] init];
// Open the database from the users filessytem
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:@"GPS.db"];
    if (sqlite3_open([databasePath UTF8String], &databaseHandle) == SQLITE_OK)
    {
        NSString *sqlStatement = [NSString stringWithFormat:@"SELECT * FROM GPSJob;"];
        sqlite3_stmt *statement;
        if(sqlite3_prepare_v2(databaseHandle, [sqlStatement UTF8String], -1, &statement, NULL) == SQLITE_OK) {
            NSLog(@"Statement prepared");
            while(sqlite3_step(statement) == SQLITE_ROW) 
            {
                [gps setJobNo:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,0)]];
                [gps setSourceMonitor:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)]];
                [gps setPositionNo:[NSNumber numberWithInt:sqlite3_column_int(statement,2)]];
                [gps setLatitude:sqlite3_column_double(statement, 3)];
                [gps setLongitude:sqlite3_column_double(statement, 4)];
                NSLog(@"Source Monitor: %@", [gps sourceMonitor]);
                [allGPS addObject:gps];
            }
        }
                    sqlite3_finalize(statement);
    }

Here is the write to .csv file method:

 GPS *saveGPS = [[GPS alloc] init];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@.csv", jobNo]];
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
    NSFileHandle *myHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
    DataController *dataController = [[DataController alloc] init];
    NSString *csvTitleString =@"Source/Monitor, PositionNumber, Latitude, Longitude \n";
    [myHandle seekToEndOfFile];
    [myHandle writeData:[csvTitleString dataUsingEncoding:NSUTF8StringEncoding]];
    NSString *csvString = [[NSString alloc] init];
    NSArray *allGPS = [[NSArray alloc]initWithArray:[dataController getAll]];
    for(int i=0;i<(allGPS.count);i++){
        saveGPS = [allGPS objectAtIndex:i];
        csvString = [NSString stringWithFormat:@"%@, %d, %f, %f \n", [saveGPS sourceMonitor], [[saveGPS positionNo] intValue], [saveGPS latitude], [saveGPS longitude]];
        [myHandle seekToEndOfFile];
        [myHandle writeData:[csvString dataUsingEncoding:NSUTF8StringEncoding]];

Solution

  • You're using always the same instance of GPS in the repeat loop so due to reference semantics the data in the object are overwritten and the same object is added to the array in each iteration.

    Move the line

    GPS *gps = [[GPS alloc] init];
    

    just before the line

    [gps setJobNo:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,0)]];
    

    to create a new GPS instance in each iteration