0

i have a NSMutableArray filled with a lot of lines like this (GPS data, 3600 lines in one hour)

51.040987|12.379154|183|599|0.0|0.0|2014-05-23T17:48:02Z|321.4

In a loop i combine these values to a xml string.

like so

xmlExport = [NSString stringWithFormat:@"%@\t\t<trackpoint>\n\t\t\t<latitude>%@</latitude>\n\t\t\t<longitude>%@</longitude>\n\t\t\t<altitudemeter>%@</altitudemeter>\n\t\t\t<altitudefeet>%@</altitudefeet>\n\t\t\t<speedkmh>%@</speedkmh>\n\t\t\t<speedmph>%@</speedmph>\n\t\t\t<datetime>%@</datetime>\n\t\t\t<degree>%@</degree>\n\t\t</trackpoint>\n", xmlExport,[CoordsArray objectAtIndex: 0], [CoordsArray objectAtIndex: 1], [CoordsArray objectAtIndex: 2], [CoordsArray objectAtIndex: 3], [CoordsArray objectAtIndex: 4], [CoordsArray objectAtIndex: 5], [CoordsArray objectAtIndex: 6], [CoordsArray objectAtIndex: 7]];

and than i want to save this data on device as an xml file, like so

NSString *fileNameCSV = [NSString stringWithFormat:@"%@/export_%@.csv", documentsDirectory, date2];
success = [csvExport writeToFile:fileNameCSV atomically:YES encoding:NSUTF8StringEncoding error:&error];

With fewer data all works fine but when i have about/over 1500 lines i get a memory problem and the app crashes, in simulator all works fine.

The problem is not to save the file, I think more it is in the for loop when combining the xml string.

Is there an other way to save the data to device?

Here my code with autoreleasepool

    for (NSString *line in coords) {

    @autoreleasepool {

        NSArray* CoordsArray = [line componentsSeparatedByString:@"|"];

        if(ExportType2==2){
            xmlExport = [NSString stringWithFormat:@"%@\t\t<trackpoint>\n\t\t\t<latitude>%@</latitude>\n\t\t\t<longitude>%@</longitude>\n\t\t\t<altitudemeter>%@</altitudemeter>\n\t\t\t<altitudefeet>%@</altitudefeet>\n\t\t\t<speedkmh>%@</speedkmh>\n\t\t\t<speedmph>%@</speedmph>\n\t\t\t<datetime>%@</datetime>\n\t\t\t<degree>%@</degree>\n\t\t</trackpoint>\n", xmlExport,[CoordsArray objectAtIndex: 0], [CoordsArray objectAtIndex: 1], [CoordsArray objectAtIndex: 2], [CoordsArray objectAtIndex: 3], [CoordsArray objectAtIndex: 4], [CoordsArray objectAtIndex: 5], [CoordsArray objectAtIndex: 6], [CoordsArray objectAtIndex: 7]];
        }

        if(ExportType2==3){
            kmlExport = [NSString stringWithFormat:@"%@,%@,%@,%@", kmlExport,[CoordsArray objectAtIndex: 1], [CoordsArray objectAtIndex: 0], [CoordsArray objectAtIndex: 2]];
        }

        if(ExportType2==4){
            gpxExport = [NSString stringWithFormat:@"%@\t\t<trkpt lat=\"%@\" lon=\"%@\">\n\t\t\t<ele>%@</ele>\n\t\t\t<time>%@</time>\n\t\t\t<magvar>%@</magvar>\n\t\t</trkpt>\n", gpxExport,[CoordsArray objectAtIndex: 0], [CoordsArray objectAtIndex: 1], [CoordsArray objectAtIndex: 2], [CoordsArray objectAtIndex: 6], [CoordsArray objectAtIndex: 7]];
        }

        //NSLog([NSString stringWithFormat:@"line: %@", line]);
        //NSLog([NSString stringWithFormat:@"gpxExport: %@", gpxExport]);

    }
}

now the app crashes also with few data

self    Class   MailBuilder 0x00115f58
coords  __NSArrayM *    @"29 objects"   0x15e5e960
line    __NSCFString *  @"51.041037|12.379055|0|0|0.0|0.0|2014-05-23T18:29:17Z|297.6"   0x15e497f0
CoordsArray __NSArrayM *    @"8 objects"    0x17dde2a0
xmlExport   NSString *  0x17d39a00  0x17d39a00
matt
  • 515,959
  • 87
  • 875
  • 1,141
Kevin
  • 115
  • 1
  • 10
  • You could also use `-[NSMutableString appendFormat:...]` which would help a great deal while maintaining your basic format. Even better would be to write the data to the file line by line which would reduce memory usage to virtually nothing. – David Berry May 23 '14 at 18:09
  • Show your code! `@autoreleasepool{}` might be all you need. – matt May 23 '14 at 18:13
  • i have edit my post and insert the code i use – Kevin May 23 '14 at 18:35
  • When you profiled this in Instruments, what did you see? You did profile this, right? – quellish May 23 '14 at 18:38
  • what from instruments i should paste here – Kevin May 23 '14 at 19:25
  • Use autorelease pools, don't use concatenate and replace to append strings, and understand that XML sucks in terms of the size explosion it represents -- even worse than JSON. – Hot Licks May 23 '14 at 20:37
  • [NSMutableString appendFormat:...] and autoreleasepool and now it works with a lot of data, thank to everyone... – Kevin May 24 '14 at 19:38

1 Answers1

4

Wrap the inside of the loop in autoreleasepool, like this:

for (...) { // or however you are looping
    @autoreleasepool {
        // .... everything else
    }
}

This will cause one loop and 1500 loops to use the same amount of memory.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • It will still use at least twice as much memory because his basic format is `string = [NSString stringWithFormat:@"%@, ...", string]` So at a minimum he has the old string and the new string. It will help, but not necessarily enough in all situations. Really, the best approach would be to write it out line-by-line. – David Berry May 23 '14 at 18:26