UIImagePickerController不在iOS 8中呈现

有没有人在iOS 8 UIImagePickerController的问题? 下面的方法在iPad上的iOS 7中工作得非常好,但是当我尝试呈现选取器(最后一行)时,在XCode 6(Beta 3或4)中运行此操作时出现以下错误。 如果这很重要,那么sourceType的select来自同一个地方的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]; } } } } 

我认为这是因为在iOS 8中,警报视图和操作表实际上是呈现的视图控制器( UIAlertController )。 所以,如果你正在展示一个新的视图控制器来响应来自UIAlertView一个动作,那么在UIAlertController被解除的UIAlertController就会出现这个UIAlertController 。 我通过延迟UIImagePickerController的显示来解决这个问题,直到runloop的下一个迭代,通过这样做:

 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self openPhotoPicker:sourceType]; }]; 

然而,解决这个问题的正确方法是在iOS 8上使用新的UIAlertController API(即使用if ([UIAlertController class])来testing它)。 这只是一个解决方法,如果你还不能使用新的API。

我同意Ben Lings问题检测。 在使用UIActionSheet时,我会build议一个更简单的解决scheme。 我只是简单地将我的代码从Action Sheetselect中移出:

 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex; { // my code } 

成:

 - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation { // my code } 

这种方式的应用程序是保证代码将在UIActionSheetanimation完成后执行。

由于UIAlertView具有类似的委托方法:

 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation { // my code } 

我想,类似的解决scheme可能适用。

这是一个为我工作的解决scheme

 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]; } 

记得要cameraUI

 UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init]; cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera; 

build立和去!

我在iOS 8中面临同样的问题。然后我看到设备上iOS 8.0.2的最新更新的更改日志。

在这个更新中提到,

“修复了阻止某些应用访问照片库中照片的问题”

因此,使用XCode 6在iOS 8.0.2版本的设备上testing您的应用程序,它将正常工作不要在iOS 8.0模拟器上testing它。

这帮助了我,希望对你也一样。

iOS 8.0.2的屏幕快照更新更改日志

 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]; } 

你可以通过使用closures显示的视图控制器(如果有的话)

 [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] } 

我build议你观看2014年WWDC会议228一边看演示控制器

我经历了很多痛苦,想出了一个适用于iPad和iPhone的解决scheme,这是最终的代码,其中一些来自其他人的评论:代码有一些错误,但是这是一个很好的开始: )

定义:

 __weak IBOutlet UIButton *attachButton; UIImage *image; 

button的动作:

  - (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解决了我的问题。

也做了丢弃和button索引的窍门。

马克斯

这是一个Xamarin解决scheme。 对我来说有效的是将我的行为添加到Dismissed事件处理程序。

 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); };