web-dev-qa-db-fra.com

Comment corriger l'avertissement "UIPopoverController is obsolète"?

J'utilise ce code:

mediaLibraryPopover = [[UIPopoverController alloc] 
                        initWithContentViewController:avc];
[self.mediaLibraryPopover presentPopoverFromRect:[theButton bounds] 
                          inView:theButton 
                          permittedArrowDirections:UIPopoverArrowDirectionAny 
                          animated:YES];

Et je reçois cet avertissement dans Xcode 7:

UIPopoverController est obsolète, d'abord déconseillé dans iOS 9.0 - UIPopoverController est obsolète. Les popovers sont maintenant implémentés sous forme de présentations UIViewController. Utilisez un style de présentation modal UIModalPresentationPopover et UIPopoverPresentationController.

45
Varun Naharia

Vous n'avez plus besoin de UIPopoverController pour présenter un contrôleur de vue. À la place, vous pouvez définir le contrôleur de vue modalPresentationStyle sur UIModalPresentationPopover.

Vous pouvez utiliser le code suivant pour cela:

avc.modalPresentationStyle = UIModalPresentationPopover;
avc.popoverPresentationController.sourceView = theButton;
[self presentViewController:avc animated:YES completion:nil];

UIModalPresentationPopover

Dans un environnement normal horizontalement, style de présentation dans lequel le contenu est affiché dans une vue contextuelle. Le contenu de l’arrière-plan est estompé et s’affiche en dehors de la fenêtre popover, ce qui provoque sa fermeture. Si vous ne souhaitez pas que les occurrences soient supprimées par les taps, vous pouvez affecter une ou plusieurs vues à la propriété passthroughViews de l'objet UIPopoverPresentationController associé, que vous pouvez obtenir à partir de la propriété popoverPresentationController.

Dans un environnement compact horizontalement, cette option se comporte de la même manière que UIModalPresentationFullScreen.

Disponible dans iOS 8.0 et versions ultérieures.

Référence Référence UIModalPresentationStyle


Vous devez définir la propriété sourceView ou barButtonItem, sinon elle plantera avec le message suivant:

*** Arrêt de l'application en raison de l'exception non capturée 'NSGenericException', raison: 'UIPopoverPresentationController (***) doit avoir un ensemble sourceView ou barButtonItem non nul précédant la présentation.'

Pour ancrer correctement la flèche de navigation, vous devez également spécifier la propriété sourceRect.

avc.modalPresentationStyle                   = UIModalPresentationPopover;
avc.popoverPresentationController.sourceView = self.view;
avc.popoverPresentationController.sourceRect = theButton.frame;
[self presentViewController:avc animated:YES completion:nil];

Reportez-vous à sourceView et sourceRect pour plus de détails.

110
Midhun MP

Apple a le moyen officiel de présenter et de configurer les popovers pour iOS8 ici: https://developer.Apple.com/library/ios/documentation/UIKit/Reference/UIPopoverPresentationController_class/index.html

Bien que similaire à la réponse de @ MidhunMP, il convient de noter le paragraphe:

Configuration du contrôleur de présentation popover après avoir appelé presentViewController:animated:completion: peut sembler contre-intuitif, mais UIKit ne crée pas de contrôleur de présentation avant le lancement de la présentation. De plus, UIKit doit attendre jusqu'au prochain cycle de mise à jour pour afficher le nouveau contenu à l'écran. Ce délai vous donne le temps de configurer le contrôleur de présentation pour votre popover.

La configuration et la réponse aux événements peuvent également être effectuées via un délégué si vous le souhaitez ( https://developer.Apple.com/library/ios/documentation/UIKit/Reference/UIPopoverPresentationControllerDelegate_protocol/index.html ).

Un exemple, mettant de côté l'utilisation du délégué:

// Present the controller using the popover style.
controller.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:controller animated:YES completion:nil];

// Popover presentation controller was created when presenting; now  configure it.
UIPopoverPresentationController *presentationController =
        [controller popoverPresentationController];
presentationController.permittedArrowDirections = UIPopoverArrowDirectionLeft;
presentationController.sourceView = containerFrameOfReferenceView;
// arrow points out of the rect specified here
presentationController.sourceRect = childOfContainerView.frame;

Mais vous voudrez aussi rejeter cela. Pour ce faire sans utiliser de délégué, votre contrôleur de présentation peut simplement appeler:

[self dismissViewControllerAnimated:YES completion:nil];

Mais que se passe-t-il si je fais pivoter mon appareil et que le popover ne pointe pas vers la bonne zone? Votre contrôleur présentateur peut le gérer:

// Respond to rotations or split screen changes
- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:nil 
                                 completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
        // Fix up popover placement if necessary, after the transition.
        if (self.presentedViewController) {
            UIPopoverPresentationController *presentationController =
                    [self.presentedViewController popoverPresentationController];
            presentationController.sourceView = containerFrameOfReferenceView;
            presentationController.sourceRect = childOfContainerView.frame;
        }
    }];
}
7
qix

Si vous le souhaitez directement depuis Button Action, ce code peut être utilisé

SecondViewController *destinationViewController = (SecondViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"second"];
destinationViewController.modalPresentationStyle = UIModalPresentationPopover;
destinationViewController.popoverPresentationController.sourceView = self.customButton;

// Set the correct sourceRect given the sender's bounds
destinationViewController.popoverPresentationController.sourceRect = ((UIView *)sender).bounds;
[self presentViewController:destinationViewController animated:YES completion:nil];
1
Abhishek