Comment puis-je corriger l’avertissement «UIPopoverController est 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ésapprouvé pour la première fois dans iOS 9.0 – UIPopoverController est obsolète. Les popovers sont maintenant implémentés en tant que présentations UIViewController. Utilisez un style de présentation modal de UIModalPresentationPopover et UIPopoverPresentationController.

Vous n’avez plus besoin d’ UIPopoverController pour présenter un contrôleur de vue. Au lieu de cela, vous pouvez définir le modalPresentationStyle of view 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 horizontal régulier, un style de présentation dans lequel le contenu est affiché dans une vue popover. Le contenu d’arrière-plan est estompé et les boutons situés en dehors du popover entraînent le rejet du popover. Si vous ne souhaitez pas que les clics soient ignorés, vous pouvez affecter une ou plusieurs vues à la propriété passthroughViews de l’object UIPopoverPresentationController associé, que vous pouvez obtenir à partir de la propriété popoverPresentationController.

Dans un environnement compact horizontalement, cette option se comporte comme UIModalPresentationFullScreen.

Disponible dans iOS 8.0 et versions ultérieures.

Référence UIModalPresentationStyle Référence


Vous devez définir la propriété sourceView ou barButtonItem , sinon il va planter avec le message suivant:

*** Terminer l’application en raison d’une exception non capturée ‘NSGenericException’, raison: ‘UIPopoverPresentationController (***) doit avoir un non-nil sourceView ou barButtonItem défini avant la présentation.’

Pour ancrer correctement la flèche pop-up, 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.

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 l’appel de presentViewController:animated:completion: peut sembler contre-intuitif, mais UIKit ne crée un contrôleur de présentation qu’après avoir initié une présentation. De plus, UIKit doit attendre le prochain cycle de mise à jour pour afficher de nouveaux contenus à 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 présentateur peut simplement appeler:

 [self dismissViewControllerAnimated:YES completion:nil]; 

Mais que faire 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)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [coordinator animateAlongsideTransition:nil completion:^(id _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; } }]; } 

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

EDIT: Concernant les votes négatifs. Tout d’abord une histoire amusante et pertinente:

http://www.folklore.org/StoryView.py?story=Negative_2000_Lines_Of_Code.txt

J’ai posté la réponse ci-dessous afin d’aider les codeurs qui auraient pu être bloqués dans la mentalité que l’iPad / iPhone nécessitait toujours des chemins d’exécution séparés lors de la présentation d’une interface utilisateur de sélecteur de média. Au moment de mon message initial, cela n’était pas clair dans les autres réponses. Ce chemin de solution a simplifié mon code et la maintenance future de mon application. Je pense que d’autres pourraient trouver cette perspective utile, car parfois, supprimer les bonnes lignes de code peut être une bonne solution.

Fin de l’édition

Si vous avez déjà un programme de travail et que vous voulez simplement vous débarrasser de l’avertissement de dépréciation, cela pourrait vous convenir.

Dans mon code, et à ma connaissance, les Popovers ont été introduits pour l’iPad et sont spécifiques à l’iPad. Apple semble avoir changé cela. Donc, si vous avez déjà un programme de travail qui utilise quelque chose comme ceci:

 if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) // use popovers else // don't use popovers 

Ce que vous pouvez faire, c’est vous débarrasser du code spécifique à l’iPad (qui est probablement le code utilisant Popovers) et faire en sorte que votre programme exécute les mêmes instructions pour iPhone et iPad. Cela a fonctionné pour moi.