UIImagePickerController не представлен в iOS 8
кто - нибудь еще имеет проблемы с UIImagePickerController в iOS 8? Метод ниже отлично работает в iOS 7 на iPad, но я получаю следующую ошибку, когда я запускаю это в XCode 6 (Beta 3 или 4), Когда я пытаюсь представить выбор (последняя строка). Если это имеет значение, выбор типа источника поступает из alertView, который представлен в том же месте.
Warning: Attempt to present <UIImagePickerController: 0x7c0ae400> on <CAGUCreateContactViewController: 0x7bf61a00> which is already presenting (null)
метод для открытия imagePicker.
- (void)openPhotoPicker:(UIImagePickerControllerSourceType)sourceType
{
if ([UIImagePickerController isSourceTypeAvailable:sourceType]) {
NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];
if ([availableMediaTypes containsObject:(NSString *)kUTTypeImage]) {
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
imagePickerController.sourceType = sourceType;
imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
imagePickerController.delegate = self;
self.imagePickerController = imagePickerController;
if (sourceType == UIImagePickerControllerSourceTypeCamera) {
[self presentViewController:self.imagePickerController animated:YES completion:nil];
} else {
if (self.popoverVC) {
[self.popoverVC dismissPopoverAnimated:YES];
self.popoverVC = nil;
}
self.popoverVC = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[self.popoverVC presentPopoverFromRect:self.nameAndPicCell.picture.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
}
}
12 ответов:
Я думаю, это потому, что в iOS 8, предупреждающие представления и листы действий на самом деле представлены контроллеры представления (
UIAlertController). Итак, если вы представляете новый контроллер вида в ответ на действие изUIAlertView, он представлен в то время какUIAlertControllerувольняют. Я работал вокруг этого, откладывая представлениеUIImagePickerControllerдо следующей итерации runloop, сделав это:[[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self openPhotoPicker:sourceType]; }];однако, правильный способ исправить это-использовать новый
UIAlertControllerAPI на iOS 8 (т. е. использоватьif ([UIAlertController class])... чтобы проверить это). Это просто обходной путь, если вы еще не можете использовать новый API.
Я согласен с Беном Линг обнаружения проблемы. Я бы предложил более простое решение в случае использования UIActionSheet. Я просто переместил свой код, который реагирует на выбор листа действий из:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex; { // my code }в:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation { // my code }таким образом, приложение гарантирует, что код будет выполнен после завершения анимации UIActionSheet.
Так как UIAlertView имеет аналогичный метод делегата:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation { // my code }Я полагаю, что подобное решение может применяться.
вот решение, которое сработало для меня
if([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0) { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self presentViewController:cameraUI animated:NO completion:nil]; }]; } else{ [controller presentViewController:cameraUI animated:NO completion:nil]; }забудьте к alloc
cameraUIUIImagePickerController *cameraUI = [[UIImagePickerController alloc] init]; cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;построить и вперед!
Я столкнулся с той же проблемой в iOS 8. Затем я увидел журнал изменений последнего обновления для iOS, т. е. 8.0.2 на устройстве.
Это упоминается в этом обновлении that_
"Исправлена проблема, которая не позволяла некоторым приложениям получать доступ к фотографиям из библиотеки фотографий"
Так что Проверьте свое приложение с помощью XCode 6 на устройстве с iOS 8.0.2 версии он будет работать нормально Не тестируйте его на iOS 8.0 simulator.
Это помогло мне, Надеюсь, то же самое для вы.
UIImagePickerController *imagePickerController= [[UIImagePickerController alloc] init]; [imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; // image picker needs a delegate so we can respond to its messages [imagePickerController setDelegate:self]; self.shouldCallViewWillAppear = NO; if(IS_IOS8) { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ // Place image picker on the screen [self presentViewController:imagePickerController animated:YES completion:nil]; }]; } else { [self presentViewController:imagePickerController animated:YES completion:nil]; }
вы можете отключить представленный контроллер вида (если таковой имеется) с помощью
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];это сработало для меня.
все, что вам нужно сделать, это отклонить уже представленный ViewController:
if (self.presentedViewController) { [self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; } [self openPhotoPicker:sourceType];если он все еще выдает ошибку, поместите openPhotoPicker: в обработчик завершения
Я просто сделал это:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, (unsigned long)NULL), ^(void) { [self retractActivePopover]; dispatch_async(dispatch_get_main_queue(), ^ { _activePopover=imagePickerPopover; UIBarButtonItem *callingButton = (UIBarButtonItem*) sender; [imagePickerPopover presentPopoverFromBarButtonItem:callingButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; }); });
на iOS 8, вы должны использовать новый API:
if (SYSTEM_VERSION_IOS_8) { self.imagePickerController.modalPresentationStyle = UIModalPresentationPopover; UIPopoverPresentationController *popPC = self.imagePickerController.popoverPresentationController; popPC.barButtonItem = self.popoverItem; popPC.permittedArrowDirections = UIPopoverArrowDirectionAny; [self presentViewController:self.imagePickerController animated:YES completion:nil] }Я рекомендую вам посмотреть 2014 WWDC сессия 228 взгляд в сторону контроллеров презентации
Я прошел через много боли, придумывая решение, которое работает как на iPad, так и на iPhone, это окончательный код, который некоторые из них приходят из комментариев других людей: в коде есть некоторые ошибки, но это очень хорошее место для начала :)
определение :
__weak IBOutlet UIButton *attachButton; UIImage *image;Действие кнопки:
- (IBAction)doAttach:(id)sender { UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:@"Select image from" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"From library",@"From camera", nil] ; [action showInView:self.view]; } #pragma mark - ActionSheet delegates - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if( buttonIndex == 1 ) { AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if(authStatus == AVAuthorizationStatusAuthorized) { NSLog(@"%@", @"You have camera access"); } else if(authStatus == AVAuthorizationStatusDenied) { NSLog(@"%@", @"Denied camera access"); [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { if(granted){ NSLog(@"Granted access to %@", AVMediaTypeVideo); } else { [self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“no camera access“ message: @“if you need to use camera in this application go to settings -> appName -> and turn on camera.” preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; NSLog(@"Not granted access to %@", AVMediaTypeVideo); return ; } }]; } else if(authStatus == AVAuthorizationStatusRestricted) { [self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“no camera access“ message: @“if you need to use camera in this application go to settings -> appName -> and turn on camera.” preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; NSLog(@"%@", @"Restricted, normally won't happen"); } else if(authStatus == AVAuthorizationStatusNotDetermined) { NSLog(@"%@", @"Camera access not determined. Ask for permission."); [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { if(granted){ NSLog(@"Granted access to %@", AVMediaTypeVideo); } else { NSLog(@"Not granted access to %@", AVMediaTypeVideo); return ; } }]; } else { [self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“No camera access“ message: @“error accusing camera” preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; return; //NSLog(@"%@", @"Camera access unknown error."); } if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { UIImagePickerController *pickerView =[[UIImagePickerController alloc]init]; pickerView.allowsEditing = YES; pickerView.delegate = self; pickerView.sourceType = UIImagePickerControllerSourceTypeCamera; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { [ self.presentedViewController dismissViewControllerAnimated:YES completion:nil ]; pickerView.modalPresentationStyle = UIModalPresentationPopover; UIPopoverPresentationController *popPC = pickerView.popoverPresentationController; popPC.sourceView = attachButton; popPC.permittedArrowDirections = UIPopoverArrowDirectionAny; [self presentViewController:pickerView animated:YES completion:nil]; } else { [self presentModalViewController:pickerView animated:YES ]; } } }else if( buttonIndex == 0 ) { ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; switch (status) { case ALAuthorizationStatusRestricted: case ALAuthorizationStatusDenied: { [self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“no access to library” message: @“if you wish to access photos in this app go to settings -> appName-> and turn on photos .” preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; [alert addAction:defaultAction]; [self presentViewController:alert animated:YES completion:nil]; } break; default: { UIImagePickerController *pickerView = [[UIImagePickerController alloc] init]; pickerView.allowsEditing = YES; pickerView.delegate = self; [pickerView setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { [ self.presentedViewController dismissViewControllerAnimated:YES completion:nil ]; pickerView.modalPresentationStyle = UIModalPresentationPopover; UIPopoverPresentationController *popup = pickerView.popoverPresentationController; popup.sourceView = attachButton; popup.permittedArrowDirections = UIPopoverArrowDirectionAny; [self presentViewController:pickerView animated:YES completion:nil]; } else { [self presentModalViewController:pickerView animated:YES ]; } } break; } } } #pragma mark - PickerDelegates - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ [self dismissModalViewControllerAnimated:true]; UIImage * img = [info valueForKey:UIImagePickerControllerEditedImage]; image = img; }
performSelector:withObject:afterDelay решить мою проблему.
также diddismisswithbuttonindex сделать трюк.
Макс
вот решение Xamarin. То, что сработало для меня, - это добавить мои действия в обработчик уволенных событий.
this.btnPhoto.TouchUpInside += (sender, e) => { actionSheet = new UIActionSheet ("Add Photo"); actionSheet.AddButton ("Take Photo"); actionSheet.AddButton ("Select from Library"); actionSheet.AddButton ("Cancel"); actionSheet.DestructiveButtonIndex = -1; // red actionSheet.CancelButtonIndex = 3; // black actionSheet.Clicked += delegate(object a, UIButtonEventArgs b) { actionSheet.Dismissed += (object aSender, UIButtonEventArgs dismissArgs) => { switch (dismissArgs.ButtonIndex) { case 0: showCamera (); break; case 1: showPhotoLibrary (); break; } }; }; actionSheet.ShowInView (view); };

Comments