You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复调用[NSString availableStringEncodings]时产生的内存泄漏问题

泄漏原因

你观测到的内存泄漏并非[NSString availableStringEncodings]方法本身导致,核心问题出在遍历编码的循环逻辑:

  • 循环内调用+[NSString stringWithContentsOfFile:encoding:error:]生成的NSString、NSError对象都是autorelease类型,会暂时缓存在当前线程的autorelease池中,直到池销毁才会释放
  • 遍历所有可用编码的逻辑会执行数十次循环,如果待读取的文件体积偏大,大量临时autorelease对象会在循环过程中累积,就会被性能检测工具识别为内存泄漏/内存峰值异常

修复方案

方案1:最小改动修复

只需要在循环内部加局部autoreleasepool,每次循环结束立即释放本次产生的临时对象即可:

- (NSString *)stringFromArchive:(NSString *)fileName inDirectory:(NSString *)folderName
{
    NSString *rStr = @"";
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *folderPath = [documentsDirectory stringByAppendingPathComponent:folderName];
    NSString *filePath = [folderPath stringByAppendingPathComponent:fileName];
    NSFileManager * fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:filePath]) {
        NSError *error;
        const NSStringEncoding *encodings = [NSString availableStringEncodings];
        NSStringEncoding encoding1;
        while ((encoding1 = *encodings++) != 0)
        {
            @autoreleasepool { // 新增局部自动释放池
                rStr = [NSString stringWithContentsOfFile:filePath encoding:encoding1 error:&error];
                if (rStr == nil) {
                    NSLog(@"error: %@", error);
                }else{
                    break;
                }
            }
        }
    }
    return rStr;
}

方案2:优化版修复(推荐)

当前遍历全量编码的逻辑效率极低,苹果已提供自动检测文件编码的原生API,无需手动遍历,从根源上避免了多次读取文件产生的临时内存:

- (NSString *)stringFromArchive:(NSString *)fileName inDirectory:(NSString *)folderName
{
    NSString *rStr = @"";
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *folderPath = [documentsDirectory stringByAppendingPathComponent:folderName];
    NSString *filePath = [folderPath stringByAppendingPathComponent:fileName];
    NSFileManager * fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:filePath]) {
        NSError *error;
        NSStringEncoding usedEncoding;
        // 系统自动检测编码,仅读取一次文件
        rStr = [NSString stringWithContentsOfFile:filePath usedEncoding:&usedEncoding error:&error];
        if (rStr == nil) {
            NSLog(@"error: %@", error);
        }
    }
    return rStr;
}

如果有特殊场景需要优先匹配指定编码,可以先自定义常用编码列表(比如UTF8、GB18030、Unicode等)逐个尝试,匹配失败再调用自动检测接口,性能远高于遍历全量编码。


内容的提问来源于stack exchange,提问作者youngmama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 06:36:03