【问题标题】:Generating string from for loop causes memory overload on iOS从 for 循环生成字符串会导致 iOS 上的内存过载
【发布时间】: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


【解决方案1】:

我没有关注问题的原因,而是关注其后果。 由于 NSString 有一个 stringByAppendingString 方法,我没有想到使用 NSMutableStrings 代替。初级开发人员的基本错误,感谢 Hot Licks、duci9y 和 Bruno Werminghoff 帮助我解决这个问题!

【讨论】:

    猜你喜欢
    • 2018-01-30
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多