【发布时间】:2014-09-21 05:16:48
【问题描述】:
所以我在这里遇到了内存问题。 我正在尝试从位置对象数组生成 GPX 字符串。
我有这个函数可以解析数组中的每个对象,并将信息添加到 GPX 字符串中。我的数组可以包含1000多个对象,所以for循环可以运行很长时间并生成很多字符串。
- (NSString *) createGPXFromPositions:(NSArray*)pPositions andHikeName:(NSString*)pHikeName{
@autoreleasepool {
NSDateFormatter *formatter;
NSString *dateString;
formatter = [[NSDateFormatter alloc] init];
//[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
formatter.dateFormat = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";
dateString = [formatter stringFromDate:[NSDate date]];
NSString *lText = @"<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"1.1\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" creator=\"MyApp\">\n\r";
lText = [NSString stringWithFormat:@"%@<trk>\n\r", lText];
lText = [NSString stringWithFormat:@"%@<name>%@</name>\n\r", lText, pHikeName];
lText = [NSString stringWithFormat:@"%@<desc>%@</desc>\n\r", lText, dateString];
lText = [NSString stringWithFormat:@"%@<trkseg>\n\r", lText];
for (int i=0; i<pPositions.count; i++) {
EMTrackPoint *lLocation = [pPositions objectAtIndex:i];
@autoreleasepool {
lText = [NSString stringWithFormat:@"%@<trkpt lat=\"%f\" lon=\"%f\">\n\r", lText, lLocation.coordinate.latitude, lLocation.coordinate.longitude];
lText = [NSString stringWithFormat:@"%@<ele>%f</ele>\n\r", lText, lLocation.altitude];
lText = [NSString stringWithFormat:@"%@<time>%@</time>\n\r", lText, [formatter stringFromDate:lLocation.timestamp]];
lText = [NSString stringWithFormat:@"%@<extensions speed=\"%f\"/>\n\r", lText, lLocation.mSpeed];
lText = [NSString stringWithFormat:@"%@</trkpt>\n\r", lText];
}
}
lText = [NSString stringWithFormat:@"%@</trkseg>\n\r", lText];
lText = [NSString stringWithFormat:@"%@</trk>\n\r", lText];
lText = [NSString stringWithFormat:@"%@</gpx>\n\r", lText];
return lText;
}
}
根据该线程的建议,我添加了我的 autoreleasepool 声明,但这无济于事: running out of memory from for loop
我从 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ }) 内部调用 createGPXFromPositions;调用:
UIApplication * application = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier background_task;
background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
//To make the code block asynchronous
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *lGPX = [mTraceRecorder createGPXFromPositions:mTraceRecorder.mUserTrace andHikeName:mHikeInfo.mName];
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
});
然而,在一些循环之后,我遇到了内存压力问题,我遇到了 didReceiveMemoryWarning,然后我的应用程序崩溃了。
我认为调用 stringWithFormat 会分配内存,但是当我使用 ARC 时,我的字符串应该在不再需要时释放,对吗? 这可能是一个菜鸟问题,但如果有人能帮助我理解我做错了什么以及我应该在这里应用哪些最佳实践,我将非常感激!
【问题讨论】:
-
从存储使用的角度来看,这是一种构建字符串的可怕方式。看看 NSMutableString。
-
使用可变字符串并附加到它,而不是每次都创建一个新字符串。
-
谢谢,这解决了我的问题!有时解决方案非常简单,以至于您根本看不到它:/是否可以将带有格式的字符串附加到 NSMutableString?带格式的字符串更容易阅读。
-
NSMutableString* str = [NSMutableString new]; [str appendFormat:@"Format here %@", @"whatever object"]
标签: ios for-loop memory-management nsstring out-of-memory