Memory spike with MoveItemAtPath
I am using the photo selector to browse and choose a video, and once it is selected, I move it from temporary storage into my working directory for future use. I do this using the following line:
[[NSFileManager defaultManager] moveItemAtPath:newName toPath:newPath error:nil];
When I profile the app, during this process the memory usage spikes to the size of the video file and then back down a moment later. Is there a way to move this file without the memory spike? I am concerned about my app crashing if the user's device has a lot of apps running at that time.
If it helps my paths look like: /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
If the memory peak is comparable to the size of the file, it could be that it's loading the entire file into memory which could indeed cause problems if the file size gets really big. The way I dealt with this problem (when copying/appending to files) is to move the file in little chunks, something like this (good old C file 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;
}
Are you "moving" across different volumes? If so, then NSFileManager will copy the file to the destination and remove the original. This copy may be causing your "memory spike".
精彩评论