UIImagePickerController non presentando in iOS 8

È chiunque altro abbia un problema con UIImagePickerController in iOS 8? Il metodo riportato di seguito funziona perfettamente in iOS 7 su iPad, ma mi da il seguente errore quando si esegue questo in XCode 6 Beta 3 o 4) quando cerco di presentare il selettore (ultima riga). Se è importante, la selezione di sourceType è venuta da un alertView che viene presentato nello stesso luogo.

Warning: Attempt to present <UIImagePickerController: 0x7c0ae400>  on <CAGUCreateContactViewController: 0x7bf61a00> which is already presenting (null)

Metodo per aprire 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];
            }
        }
    }
}
  • Hai fatto a risolverlo?
  • Non ancora; il selettore viene effettivamente visualizzato, ma ho ancora ottenere gli errori nella console.
  • In iOS 9 e funziona correttamente.
InformationsquelleAutor Dave | 2014-07-24



12 Replies
  1. 108

    Credo che questo è perché in iOS 8, avviso di vedute e di azione fogli sono effettivamente presentati view controller (UIAlertController). Quindi, se si presenta un nuovo controller di visualizzazione in risposta a un’azione da UIAlertView, viene presentato mentre il UIAlertController è respinto. Ho lavorato intorno a questo, ritardando la presentazione del UIImagePickerController fino alla prossima iterazione del runloop, in questo modo:

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

    Tuttavia, il modo corretto per risolvere questo problema è quello di utilizzare la nuova UIAlertController API di iOS 8 (cioè l’uso if ([UIAlertController class]) … a test). Questa è solo una soluzione, se non è possibile utilizzare le nuove API di sicurezza.

    • Questo ha funzionato per me..grazie
    • Il modo corretto per risolvere questo problema è quello di utilizzare la nuova UIActionController API di iOS 8 (utilizzo if ([UIActionController class]) ... a test). Questa è solo una soluzione, se non è possibile utilizzare le nuove API di sicurezza.
    • Non dovrebbe essere UIAlertController, non UIActionController?
    • hai ragione, che dovrebbe essere UIAlertController.
    • Questo non funziona per me… Utilizzando 8.1.1 iPad Mini
    • Questo funziona per iPhone con iOS8, ma non con l’iPad.
    • Per me ha funzionato su iOS 8 simulator, effettuerà il controllo sul dispositivo.
    • Questo lavorato sia su iphone e ipad dispatch_async(dispatch_get_main_queue()) { // Code here }
    • È inoltre possibile utilizzare un NSTimer e pianificare con un .5f secondi di ritardo con il ” NO ” come ripetere. Il UIActionSheet vista ha bisogno di essere licenziato prima di poter eseguire segue. Provate a chiamare un nuovo metodo da: [NSTimer scheduledTimerWithTimeInterval:.5f target:self selector:@selector(YOURMETHODHERE) userInfo:nil repeats:NO];
    • Bello Soluzioni. Funziona per me. Grazie!
    • La tua spiegazione è grande, ma perché non chiudere l’azione precedente foglio prima? (Come nel Rituale della soluzione qui di seguito)

  2. 80

    Sono d’accordo con Ben Ling problema di rilevamento. Vorrei suggerire una soluzione più semplice a caso, quando si utilizza UIActionSheet. Ho semplicemente spostato il mio codice che reagisce su Azione di selezione Fogli da:

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

    in:

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

    In questo modo l’app viene garantito il codice che verrà eseguito DOPO UIActionSheet animazione finiture.

    Dal UIAlertView è simile metodo delegato:

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

    Suppongo che simile soluzione potrebbe applicare.

    • Soluzione perfetta per me. Grazie.
    • Questa è la risposta corretta, come funziona bene in entrambi iOS7 e iOS8. Grazie mille
    • Questa dovrebbe essere la risposta corretta. Come NSOperationQueue potrebbe cambiare in qualsiasi momento con i nuovi aggiornamenti di versione e di interruzione di corrente, la risposta selezionata dal lavoro.
    • Penso che questo sia il modo corretto anche!. Tuttavia ritengo che questo sia un bug che Apple non potrà mai risolvere. Questo è il mio caso: ho un pulsante “condividi” che mostra un UIActionSheet con due pulsanti di chiusura con zip e copia negli appunti” e l’altro “la stampa”. Rendere il file zip prende un po’, così si è fatto, mentre il nascondiglio di animazione si svolge, che è il motivo per cui preferisco clickedButtonAtIndex:. La stampante interazione controller ha la stessa limitazione, come la foto del controller, in questo thread, quindi ha a iniziare da didDismissWithButtonIndex: questo significa che ho bisogno di avere la mia logica, diviso in due metodi? che pasticcio!
    • Sarei più felice che hanno aggiunto sia il completamento di chiamate in un metodo. Uno permetterebbe di reagire il più presto possibile dopo che l’utente ha cliccato il pulsante e altri consentono di proseguire con l’aggiornamento di UI con i risultati della stessa e fare clic su azione. Ma che distruggerebbe le loro API semplice modello/did eventi.
    • Questo funziona perfettamente. Questa dovrebbe essere la risposta

  3. 12

    Qui è una soluzione che ha funzionato per me

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

    Ricordarsi di alloc cameraUI

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

    Costruire e Vai!

  4. 8

    Stavo affrontando lo stesso problema in iOS 8.
    Poi ho visto il cambiamento di registro con l’ultimo aggiornamento di iOS, cioè 8.0.2 sul dispositivo.

    È menzionato in questo aggiornamento that_

    “Consente di correggere un problema che impediva ad alcune applicazioni di accedere le foto dalla Libreria di Foto”

    In modo da testare la tua app con XCode 6 sul dispositivo con iOS 8.0.2 versione funziona benissimo
    Non prova su iOS 8.0 simulatore.

    Questo mi ha aiutato, spero lo stesso per voi.

    UIImagePickerController non presentando in iOS 8

  5. 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];
    }
  6. 3

    È possibile eliminare l’presentato view controller (se del caso) utilizzando

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

    Questo ha funzionato per me.

    • Questo ha funzionato per me – appena inserito questa riga prima di presentare il nuovo controller di visualizzazione. Perché non hanno più voti? Qualcuno ha avuto un problema con questa soluzione?
  7. 2

    Tutto quello che dovete fare è chiudere già presentato ViewController:

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

    Se produce ancora errore, mettere openPhotoPicker: al gestore di completamento

    • grazie eroe. lavorando come un fascino.
  8. 1

    Ho semplicemente fatto questo:

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

    Su iOS 8 si dovrebbe utilizzare nuove 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]
    }

    Vi consigliamo di guardare il 2014 WWDC sessione 228 un’occhiata a lato di presentazione controller

    • L’ultima riga dovrebbe essere [self presentViewController:self.imagePickerController animated:YES completion:nil];. Inoltre, mentre questa è una grande sapere, il vecchio metodo funziona ancora su iOS8 e reimplementando con le nuove API non risolvere questo particolare problema nella mia esperienza.
    • Questo non risolve il problema, e come Clafou dice, il showViewController linea è sbagliato e provoca un incidente.
  10. 1

    Sono andato attraverso un sacco di dolore a venire con una soluzione che funziona sia su iPad e iPhone, questo è il codice finale che alcuni si tratta di commenti di altre persone:
    il codice ha qualche bug ma è un ottimo posto per iniziare 🙂

    definizioni :

    __weak IBOutlet UIButton *attachButton;
    UIImage *image;

    azione del pulsante :

        - (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;
    
    }
  11. 0

    performSelector:withObject:afterDelay risolto il mio problema.

    anche didDismissWithButtonIndex fare il trucco.

    Max

    • Il passaggio da clickButtonAtIndex per didDismissWithButtonIndex è stata la più semplice e la soluzione migliore per me.
  12. 0

    Ecco un Xamarin soluzione. Che cosa ha funzionato per me è stato quello di aggiungere le mie azioni a un ha Respinto gestore di eventi.

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

Lascia un commento