问题:
当我的应用程序录制的视频大小/时长过大时,如果视频长度过长(例如使用UIImagePickerControllerQualityTypeMedium录制了30分钟或更多,或者使用UIImagePickerControllerQualityTypeIFrame1280x720录制了超过一分钟),保存视频时应用程序会崩溃,没有日志/异常。
我的设置:
在我的应用中,我使用UIImagePickerController来录制视频。现在我注意到,如果我让我的视频长度非常长(例如使用UIImagePickerControllerQualityTypeMedium录制了30分钟或更长时间,或使用UIImagePickerControllerQualityTypeIFrame1280x720录制了超过一分钟),那么在保存视频时应用程序会崩溃。有时带有警告,有时没有。现在我开始调试并注意到它与内存(malloc_error)有关。
我使用探查器实时检查分配情况,并注意到当即将保存视频时,分配突然变得非常大(我猜与视频的临时内存使用有关?)然后最终崩溃。这是来自探查器的屏幕截图: 该应用程序必须能够记录具有最大持续时间为1小时的视频(在任何指定的质量下)。 我尝试过的事情:
我使用探查器实时检查分配情况,并注意到当即将保存视频时,分配突然变得非常大(我猜与视频的临时内存使用有关?)然后最终崩溃。这是来自探查器的屏幕截图: 该应用程序必须能够记录具有最大持续时间为1小时的视频(在任何指定的质量下)。 我尝试过的事情:
- 设置picker.videoMaximumDuration更短/更长
- 使用探查器/工具进行调试
- 检查泄漏
- 关闭所有打开的应用程序并删除设备上的应用程序(用于存储清理)以获取更多内存
- (void)openCamera:(id)sender context:(NSManagedObjectContext*)context {
self.context = context;
//Set self as delegate (UIImagePickerControllerDelegate)
[self.picker setDelegate:self];
//If the device has a camera
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.picker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.picker.allowsEditing = YES;
self.picker.videoQuality = [Settings videoQualitySetting];
//If the camera can record video
NSString *desired = (NSString *)kUTTypeMovie;
if ([[UIImagePickerController availableMediaTypesForSourceType:self.picker.sourceType] containsObject:desired]) {
//Let the user record video
self.picker.mediaTypes = [NSArray arrayWithObject:desired];
self.picker.videoMaximumDuration = MaxDuration;
}
else {
NSLog(@"Can't take videos with this device"); //debug
}
//Present the picker fullscreen/in popover
if ([Settings shouldDisplayFullScreenCamera]){
[self presentModalViewController:self.picker animated:YES];
[self.masterPopoverController dismissPopoverAnimated:YES];
}
else {
if (!_popover){
_popover = [[UIPopoverController alloc] initWithContentViewController:self.picker];
}
[_popover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
else {
NSLog(@"Does not have a camera"); //debug
}
}
当选择图片时,需编写以下代码:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
// Save the video, and close the overlay
if (CFStringCompare ((__bridge CFStringRef) mediaType, kUTTypeMovie, 0)
== kCFCompareEqualTo) {
self.tempVideoPath = [[info objectForKey:
UIImagePickerControllerMediaURL] path];
[LocalVideoStorage saveVideo:[NSData dataWithContentsOfPath:self.tempVideoPath name:self.videoName];
[_picker dismissModalViewControllerAnimated: YES];
[[_picker parentViewController] dismissModalViewControllerAnimated:YES];
[_popover dismissPopoverAnimated:YES];
}
}
最后,当它被保存时:
+ (NSString*)saveVideo:(NSData*)video:(NSString*)videoName {
NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.MOV", videoName]]; //add our video to the path
[fileManager createFileAtPath:fullPath contents:video attributes:nil]; //finally save the path (video)
NSLog(@"Video saved!");
return fullPath;
}
我正在使用iOS 5.1.1的ARC。
更新: 我在malloc_error_break上设置了断点,在instruments中可以看到它被调用于:
# Address Category Timestamp Live Size Responsible Library Responsible Caller
0 0x10900000 Malloc 473,29 MB 02:08.951.332 • 496283648 Foundation -[NSData(NSData) initWithContentsOfFile:]
解决方案: 如lawicko和john.k.doe所说,我尝试将视频从其路径加载到NSData变量中。这导致整个视频被加载到内存中。现在,我只是移动文件(并重命名)copyItemAtPath
NSError *error = nil;
if (![fileManager copyItemAtPath:path toPath:fullPath error:&error])
NSLog(@"Error: %@", error);
# 地址 类别 时间戳 现场 大小 负责的库 负责的调用者 0 0x10900000 Malloc 473,29 MB 02:08.951.332 • 496283648 Foundation -[NSData(NSData) initWithContentsOfFile:]
- Thermometer