【问题标题】:Memory spike with MoveItemAtPathMoveItemAtPath 的内存峰值
【发布时间】:2011-10-10 19:19:42
【问题描述】:

我正在使用照片选择器来浏览和选择一个视频,一旦选择了它,我就会将它从临时存储移动到我的工作目录以供将来使用。我使用以下行来执行此操作:

[[NSFileManager defaultManager] moveItemAtPath:newName toPath:newPath error:nil];

当我对应用程序进行分析时,在此过程中,内存使用量会飙升至视频文件的大小,然后稍后又回落。有没有办法在没有内存峰值的情况下移动这个文件?如果用户的设备当时运行了很多应用程序,我担心我的应用程序会崩溃。

如果它有助于我的路径如下所示: /private/var/mobile/Applications/046F9A22-DBEC-436F-936C-D59945783483/tmp//trim.PK4abv.MOV

/private/var/mobile/Applications/046F9A22-DBEC-436F-936C-D59945783483/Documents/resources/myCards/BC742DC8-A7D4-40B8-8AC8-97CF9F242881/trim.PK4abv.MOV

【问题讨论】:

    标签: iphone objective-c ios


    【解决方案1】:

    如果内存峰值与文件大小相当,则可能是将整个文件加载到内存中,如果文件大小变得非常大,这确实会导致问题。我处理这个问题的方法(复制/附加到文件时)是将文件分成小块移动,就像这样(好的旧 C 文件 API):

    #import <sys/stat.h>
    
    +(BOOL) moveFileAtPath:(NSString*)sourcePath 
              toFileAtPath:(NSString*)targetPath 
          inChunksWithSize:(size_t)bytes {
    
        // open target file for appending
        FILE *targetFile = fopen([targetPath UTF8String], "a");
        if(targetFile == NULL)
            return NO;
    
        FILE *sourceFile = fopen([sourcePath UTF8String], "rb");
        if(appendFile == NULL) {
            fclose(targetFile);
            return NO;
        }
    
        void *data = malloc(bytes); 
        if (data == NULL) {
            fclose(targetFile);
            fclose(sourceFile);
            return NO;
        }
    
        size_t sourceSize = (size_t)filelength(fileno(sourceFile));
        off_t currentOffset = 0;
    
        while (currentOffset < sourceSize) {
            fseeko(sourceFile, currentOffset, SEEK_SET);
            size_t read_bytes = fread(data, 1, bytes, sourceFile);
            fwrite(data, 1, read_bytes, targetFile);
            currentOffset += read_bytes;
            if (read_bytes < 1)
                break;
        }
    
        free(data);
        fclose(targetFile);
        fclose(sourceFile);
    
        return YES;
    }
    

    【讨论】:

    • 非常感谢!现在试试这个
    • 如果您只是将现有文件从一个位置移动到另一个位置,这真的是大材小用。您可以只使用重命名()。当源和目标都在同一个卷上时,这就是 NSFileManager 应该做的,因此我的回答是。我很想知道您的应用程序的文件系统活动输出(带有回溯)。
    【解决方案2】:

    您是否正在跨不同的卷“移动”?如果是这样,那么 NSFileManager 会将文件复制到目的地并删除原始文件。此副本可能会导致您的“内存峰值”。

    【讨论】:

    • 不,我正在从临时文件(选择它们时放置视频的位置)和我的应用程序文档文件夹中移动,这是在 iphone/ipad 顺便说一句
    猜你喜欢
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多