The*_*ter 6 iphone crash uiimagepickercontroller ipad ios
问题:
保存我的应用中记录的视频时,如果视频大小/持续时间太大/太长,我的应用程序崩溃时没有日志/异常.
我的设置:
在我的应用程序中,我使用UIImagePickerController来录制视频.现在我注意到如果我的视频长度非常长(例如使用UIImagePickerControllerQualityTypeMedium 30分钟,或使用UIImagePickerControllerQualityTypeIFrame1280x720超过一分钟),保存视频时应用程序崩溃.有时有,有时没有警告.现在我开始调试并注意到它与内存有关(malloc_error).
我使用分析器来实时检查分配,并注意到,当它要保存视频时,分配突然变得非常大(我想这与视频的临时内存使用情况有关?)在它最终崩溃之前.以下是分析器的屏幕截图:

该应用必须能够录制最长1小时的视频(指定任何质量).
我尝试过的:
码:
- (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
}
}
Run Code Online (Sandbox Code Playgroud)
选择图像时的代码:
- (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];
}
}
Run Code Online (Sandbox Code Playgroud)
最后,当它被保存时:
+ (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;
}
Run Code Online (Sandbox Code Playgroud)
我在iOS 5.1.1中使用ARC
更新: 我在malloc_error_break上放了一个断点,在仪器中我可以看到它来自:
# Address Category Timestamp Live Size Responsible Library Responsible Caller
0 0x10900000 Malloc 473,29 MB 02:08.951.332 • 496283648 Foundation -[NSData(NSData) initWithContentsOfFile:]
Run Code Online (Sandbox Code Playgroud)
解决方案: 正如lawicko&john.k.doe所说,我试图将视频从它的路径加载到NSData变量中.这导致整个视频被加载到内存中.我现在只是移动文件(&rename)copyItemAtPath而不是这样做
NSError *error = nil;
if (![fileManager copyItemAtPath:path toPath:fullPath error:&error])
NSLog(@"Error: %@", error);
Run Code Online (Sandbox Code Playgroud)
law*_*cko 10
你的问题是这一行:
[NSData dataWithContentsOfPath:self.tempVideoPath]
Run Code Online (Sandbox Code Playgroud)
您显然是在尝试将此文件的内容一次性加载到内存中,但iOS绝不会让您一次加载这么多内容.您的saveVideo方法似乎只将文件从临时位置复制到文档目录.如果这是您需要做的唯一事情,那么请看一下copyItemAtPath:toPath: NSFileManager的错误方法.您可以更改saveVideo方法以将临时文件路径作为参数而不是数据.