web-dev-qa-db-de.com

UIImagePickerController wird in iOS 8 nicht angezeigt

Hat jemand anderes ein Problem mit UIImagePickerController in iOS 8? Die folgende Methode funktioniert auf iOS-Geräten auf einem iPad einwandfrei. Ich erhalte jedoch die folgende Fehlermeldung, wenn ich diese Option in XCode 6 (Beta 3 oder 4) starte, wenn ich versuche, den Picker (letzte Zeile) zu präsentieren. Wenn es darauf ankommt, stammt die Auswahl des Quellentyps aus einer alertView, die an derselben Stelle angezeigt wird.

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

Methode zum Öffnen von 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];
            }
        }
    }
}
56
Dave

Ich denke, das liegt daran, dass in iOS 8 Warnmeldungen und Aktionsblätter tatsächlich Ansichts-Controller (UIAlertController) dargestellt werden. Wenn Sie also einen neuen View-Controller als Reaktion auf eine Aktion aus der UIAlertView präsentieren, wird dieser angezeigt, während die UIAlertController abgewiesen wird. Ich habe dieses Problem gelöst, indem ich die Präsentation der Variable UIImagePickerController bis zur nächsten Iteration des Runloops verzögert habe, indem ich Folgendes ausführte:

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

Um dies zu beheben, verwenden Sie jedoch die neue UIAlertController-API unter iOS 8 (d. H. Verwenden Sie if ([UIAlertController class]) ..., um dies zu testen). Dies ist nur eine Problemumgehung, wenn Sie die neue API noch nicht verwenden können.

108
Ben Lings

Ich stimme der Problemerkennung von Ben Lings zu. Ich würde eine einfachere Lösung vorschlagen, falls Sie UIActionSheet verwenden. Ich habe einfach meinen Code verschoben, der auf die Auswahl des Aktionsblatts reagiert: 

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

in:

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

Auf diese Weise ist die App garantiert, dass der Code ausgeführt wird, nachdem die Animation von UIActionSheet beendet ist.

Da UIAlertView eine ähnliche Delegatmethode hat:

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

Ich denke, dass eine ähnliche Lösung zutreffen kann.

80
vedrano

Hier ist eine Lösung, die für mich funktioniert hat

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

Denken Sie daran, cameraUI zuzuweisen.

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

Build and Go!

12

Ich hatte das gleiche Problem in iOS 8. Dann sah ich das Änderungsprotokoll des neuesten Updates für iOS, d. H. 8.0.2 auf dem Gerät.

In diesem Update wird erwähnt, dass_

"Behebt ein Problem, durch das einige Apps nicht auf Fotos aus der Fotobibliothek zugreifen konnten"

Testen Sie Ihre App mit XCode 6 auf dem Gerät mit der Version iOS 8.0.2. Es funktioniert problemlos Testen Sie sie nicht auf dem iOS 8.0-Simulator.

Das hat mir geholfen, ich hoffe dasselbe für dich.

Screen-shot of iOS 8.0.2 Update change log

8
Piyush Mathur
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];
}
4
Nirav Gadhiya

Sie können den präsentierten View-Controller (falls vorhanden) mit beenden 

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

Das hat bei mir funktioniert.

3
Ritu

Sie müssen lediglich den bereits präsentierten ViewController abweisen:

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

[self openPhotoPicker:sourceType];

Wenn der Fehler immer noch auftritt, setzen Sie openPhotoPicker: in Completion-Handler

2
Nikolay Krasnov

Unter iOS 8 sollten Sie die neue API verwenden:

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

Ich empfehle Ihnen, die WWDC-Sitzung 2014 228 in den Seiten-Präsentationscontrollern zu sehen

1
Vito Ziv

Ich habe eine Menge Schmerz durchgemacht, als ich eine Lösung gefunden habe, die sowohl auf dem iPad als auch auf dem iPhone funktioniert. Dies ist der letzte Code, der zum Teil aus den Kommentaren anderer Personen stammt: anfangen :) 

definitionen:

__weak IBOutlet UIButton *attachButton;
UIImage *image;

aktion der Schaltfläche: 

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

}
1
Omid S.

Ich habe einfach das gemacht:

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

    });

});
1

Hier ist eine Xamarin-Lösung. Was für mich funktionierte, war das Hinzufügen meiner Aktionen zu einem abgemeldeten Ereignishandler.

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

performSelector: withObject: afterDelay hat mein Problem gelöst.

auch didDismissWithButtonIndex macht den Trick.

Max

0
masgar