當保存該記錄在我的應用程序的視頻,如果視頻大小/持續時間過大/長,沒有我的應用程序崩潰日誌/例外。
我的設置:
在我的應用我使用的UIImagePickerController錄製視頻。現在我注意到,如果我製作的視頻長度很長(例如UIImagePickerControllerQualityTypeMedium爲30分鐘,或UIImagePickerControllerQualityTypeIFrame1280x720超過一分鐘),則在保存視頻時,應用程序會崩潰。有時會有,有時沒有警告。現在我開始調試並注意到它與內存有關(malloc_error)。
我使用profiler來檢查分配情況,並注意到當它要保存視頻時,分配突然變得非常大(我猜這是與視頻的臨時內存使用情況有關?),然後才最終崩潰。這裏是探查器的屏幕截圖:
該應用程序必須能夠記錄最長持續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;
}
我使用ARC與iOS 5.1 .1
更新: 我已經把上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:]
解決方案: 作爲lawicko & john.k.doe說,我試圖加載從視頻它是進入NSData變量的路徑。這導致整個視頻被加載到內存中。相反,這樣做的,我現在只是移動文件(&重命名)copyItemAtPath
你能找到哪種類型的對象有最大的活動字節? – nhahtdh
@nhahtdh它說,它被稱爲上:'#\t地址\t類別\t時間戳\t直播\t尺寸\t負責圖書館\t負責來電 0x10900000 \t的malloc 473,29 MB \t 02:08.951.332 \t•基金會\t - [NSData(NSData)initWithContentsOfFile:] ' – Thermometer
'[LocalVideoStorage saveVideo:[NSData dataWithContentsOfPath:self.tempVideoPath] ...'您正在將整個臨時文件讀入一個NSData對象,僅將其保存到磁盤。難道你不能把臨時文件複製到你選擇的永久存儲文件夾中嗎? – Rog