【问题标题】:UIImagePickerController not presenting in iOS 8UIImagePickerController 未出现在 iOS 8 中
【发布时间】:2014-09-16 12:20:46
【问题描述】:

还有其他人在 iOS 8 中遇到UIImagePickerController 的问题吗?下面的方法在 iPad 上的 iOS 7 中运行良好,但是当我在 XCode 6(Beta 3 或 4)中运行该方法时,当我尝试显示选择器(最后一行)时,会出现以下错误。如果重要的话,sourceType 的选择来自于显示在同一位置的 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 9 及更高版本中工作正常。

标签: ios ipad uiimagepickercontroller ios8


【解决方案1】:

在 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 session 228 a look in side presentation controllers

【讨论】:

  • 最后一行应该是[self presentViewController:self.imagePickerController animated:YES completion:nil];。此外,虽然很高兴知道这一点,但旧方法仍然适用于 iOS8,并且根据我的经验,使用新 API 重新实现并不能解决这个特定问题。
  • 这并不能解决问题,正如 Clafou 所说,showViewController 行错误并导致崩溃。
【解决方案2】:

我认为这是因为在 iOS 8 中,警报视图和操作表实际上是呈现视图控制器 (UIAlertController)。因此,如果您正在呈现一个新的视图控制器以响应来自 UIAlertView 的操作,那么它会在 UIAlertController 被解除时呈现。我通过将UIImagePickerController 的呈现延迟到运行循环的下一次迭代来解决这个问题,这样做:

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

但是,解决此问题的正确方法是在 iOS 8 上使用新的 UIAlertController API(即使用 if ([UIAlertController class]) ... 对其进行测试)。如果您还不能使用新 API,这只是一种解决方法。

【讨论】:

  • 解决此问题的正确方法是在 iOS 8 上使用新的UIActionController API(使用if ([UIActionController class]) ... 对其进行测试)。如果您还不能使用新 API,这只是一种解决方法。
  • @BenLings 不应该是UIAlertController,而不是UIActionController吗?
  • @PeterHeide - 你是对的,应该是UIAlertController
  • 在 iOS 8 模拟器上为我工作,将在设备上进行检查。
  • 这适用于 iphone 和 ipad dispatch_async(dispatch_get_main_queue()) { // Code here }
【解决方案3】:

这是一个对我有用的解决方案

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;

构建并开始!

【讨论】:

    【解决方案4】:
    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];
    }
    

    【讨论】:

      【解决方案5】:

      我只是这样做了:

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

      【讨论】:

        【解决方案6】:

        我同意 Ben Lings 的问题检测。如果使用 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
        }
        

        我想类似的解决方案可能适用。

        【讨论】:

        • 对我来说是完美的解决方案。谢谢。
        • 这是正确的答案,因为它在 iOS7 和 iOS8 下都可以正常工作。非常感谢
        • 这应该是正确的答案。由于 NSOperationQueue 可能会随着新版本的更新而随时更改,并使当前选择的答案无法正常工作。
        • 我认为这也是正确的方法!。但是,我认为这是 Apple 永远无法解决的错误。这是我的情况:我有一个“共享”按钮,它显示一个UIActionSheet,带有两个按钮“压缩并复制到剪贴板”和另一个“打印”。制作 zip 文件需要一些时间,所以它是在隐藏动画发生时完成的,这就是我更喜欢 clickedButtonAtIndex: 的原因。打印机交互控制器与此线程中的照片控制器具有相同的限制,因此它必须从 didDismissWithButtonIndex: 开始,这意味着我需要将我的逻辑分为两种方法吗?真是一团糟!
        • 我会更高兴他们在一种方法中添加了两个完成调用。一个可以让您在用户单击按钮后尽快做出反应,另一个可以让您继续使用相同的点击和操作的结果更新 UI。但这会破坏他们简单的 API 模式将/执行事件。
        【解决方案7】:

        我在 iOS 8 中遇到了同样的问题。 然后我在设备上看到了 iOS 的最新更新(即 8.0.2)的更改日志。

        本次更新中提到了_

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

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

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

        【讨论】:

          【解决方案8】:

          您需要做的就是关闭已经呈现的 ViewController:

          if (self.presentedViewController) {
              [self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
          }
          
          [self openPhotoPicker:sourceType];
          

          如果仍然产生错误,请将 openPhotoPicker: 放入完成处理程序

          【讨论】:

            【解决方案9】:

            performSelector:withObject:afterDelay 解决了我的问题。

            didDismissWithButtonIndex 也可以解决问题。

            最大

            【讨论】:

            • clickButtonAtIndex 切换到didDismissWithButtonIndex 对我来说是最简单、最好的解决方案。
            【解决方案10】:

            这是一个 Xamarin 解决方案。对我有用的是将我的操作添加到 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);
            };
            

            【讨论】:

              【解决方案11】:

              我在想出一个适用于 iPad 和 iPhone 的解决方案时经历了很多痛苦,这是最终代码,其中一些来自其他人的 cmets: 代码有一些错误,但这是一个很好的起点:)

              定义:

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

              【讨论】:

                【解决方案12】:

                您可以使用

                关闭呈现的视图控制器(如果有)
                [self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
                

                这对我有用。

                【讨论】:

                • 这对我有用——只是在展示新的视图控制器之前插入了这一行。为什么这没有更多的赞成票?有人对此解决方案有疑问吗?
                猜你喜欢
                • 1970-01-01
                • 2014-11-06
                • 1970-01-01
                • 2015-01-06
                • 1970-01-01
                • 2015-04-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多