2014-07-24 29 views
56

是否有其他人在iOS 8中與UIImagePickerController有問題?下面的方法在iPad上的iOS 7中運行得非常好,但是當我嘗試呈現選取器(最後一行)時,我在XCode 6(Beta 3或4)中運行此操作時遇到以下錯誤。如果它很重要,sourceType的選擇來自同一位置顯示的alertView。UIImagePickerController不在iOS 8中呈現

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

你解決了嗎? –

+0

還沒有;選取器實際顯示,但我仍然在控制檯中出現錯誤。 – Dave

回答

107

我想這是因爲在iOS 8的,警惕的觀點和行動表實際上是提出了視圖控制器(UIAlertController)。因此,如果您要呈現新的視圖控制器以響應UIAlertView的操作,則會在UIAlertController被解除時顯示該視圖控制器。我工作圍繞這通過延遲UIImagePickerController的呈現,直到runloop的下一次迭代,這樣做:

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

然而,解決這一問題的正確方法是使用新UIAlertController API在iOS 8(即使用if ([UIAlertController class]) ...來測試它)。如果您還不能使用新的API,這只是一種解決方法。

+0

這對我有效..謝謝 –

+2

解決這個問題的正確方法是在iOS 8上使用新的'UIActionController' API(使用'if([UIActionController class])...'來測試它)。如果您還不能使用新的API,這只是一種解決方法。 –

+0

@BenLings不應該是'UIAlertController',而不是'UIActionController'? –

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

+1

最後一行應該是'[self presentViewController:self.imagePickerController animated:YES completion:nil];'。此外,雖然這很瞭解,但舊方法仍然適用於iOS8,並且使用新API重新實現並不能解決我的經驗中的這個特定問題。 – Clafou

+0

這不能解決問題,正如Clafou所說,showViewController行是錯誤的並導致崩潰。 – w0mbat

12

這裏是一個解決方案,爲我

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

我只是這樣做:

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

    }); 

}); 
80

我同意本Lings問題檢測。如果使用UIActionSheet,我會建議一個更簡單的解決方案。我只是提出我的代碼,在行動表上選擇從反應:

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

到:

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

這樣的應用程序是guarantied代碼後會UIActionSheet動畫完成執行。

由於UIAlertView中也有類似的委託方法:

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

我假定類似溶液可以適用。

+2

對我來說是完美的解決方案。謝謝。 –

+2

這是正確的答案,因爲它在iOS7和iOS8下均可正常工作。非常感謝 – Sobakus

+2

這應該是正確的答案。由於NSOperationQueue可以在任何時候隨着新版本更新而改變,並打破當前選定的工作答案。 – Drmorgan

8

我在iOS 8中遇到了同樣的問題。 然後,我看到了設備上最新iOS更新日誌(即8.0.2)。

它在本次更新中提到that_

「修復了阻止某些應用程序從圖片庫訪問照片的問題」

因此,使用的XCode 6設備上的iOS 8.0.2版本測試您的應用它將正常工作 不要在iOS 8.0模擬器上測試它。

這幫了我,希望對你也一樣。

Screen-shot of iOS 8.0.2 Update change log

2

所有你需要做的就是解僱已經出現的ViewController:

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

[self openPhotoPicker:sourceType]; 

如果仍然產生錯誤,把openPhotoPicker:完成處理

+0

謝謝英雄。像魅力一樣工作。 –

0

performSelector:withObject:afterDelay解決了我問題。

也didDismissWithButtonIndex做的伎倆。

最大

+0

從'clickButtonAtIndex'切換到'didDismissWithButtonIndex'對我來說是最簡單和最好的解決方案。 – duncanc4

0

這是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); 
}; 
1

我經歷了很多痛苦的去想出這兩個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; 

} 
3

您可以通過使用

[self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; 

這爲我工作駁回呈現視圖控制器(如果有的話)。

+0

這工作對我來說 - 只是在呈現新視圖控制器之前插入此行。爲什麼這沒有更多的票?有沒有人有這個解決方案的問題? – IanS

相關問題