J'utilise un scénario de storyboard qui présente un contrôleur de vue comme popover. Le seque a pour coutume une variable UIView
. Sur les versions antérieures à iOS9, la fenêtre popover pointait correctement vers le bas au centre de la variable UIView
personnalisée (présentée sous UIView). Sur iOS9, il pointe vers le coin supérieur gauche de la UIView
.
J'ai essayé de retrouver tous les appels de sélecteur dans la variable personnalisée UIView
pour savoir si je devais implémenter quelque chose que je devais implémenter dans ma variable personnalisée UIView
afin de fournir le "point d'accès" pour le popover, mais je n'ai rien trouvé
Des idées..? Merci
_ {Merci à @Igor Camilo pour sa réponse - au cas où cela serait utile à certains, voici comment j'ai corrigé cela dans mon code} _:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIPopoverPresentationController* possiblePopOver = segue.destinationViewController.popoverPresentationController;
if (possiblePopOver != nil) {
//
// iOS9 -- ensure correct sourceRect
//
possiblePopOver.sourceRect = possiblePopOver.sourceView.bounds;
}
...
}
_ {Exemple: Le bouton 'Court' déclenche un popover, le popover pointe sur le coin supérieur gauche du contrôle 'Trier'
J'ai eu exactement le même problème. Je viens de le résoudre en définissant sourceRect dans prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segue.identifier {
case "Popover Identifier"?:
if #available(iOS 9.0, *) {
segue.destinationViewController?.popoverPresentationController?.sourceRect = anchorView.bounds
}
default:
break
}
}
J'avais le même problème, mais mon application comportait une multitude de fenêtres publicitaires intempestives. J'ai donc créé une fonction centralisée pour le correctif (mais je devais quand même l'utiliser sur tous les contrôleurs de vue dotés de fenêtres contextuelles).
// Fix for IOS 9 pop-over arrow anchor bug
// ---------------------------------------
// - IOS9 points pop-over arrows on the top left corner of the anchor view
// - It seems that the popover controller's sourceRect is not being set
// so, if it is empty CGRect(0,0,0,0), we simply set it to the source view's bounds
// which produces the same result as the IOS8 behaviour.
// - This method is to be called in the prepareForSegue method override of all
// view controllers that use a PopOver segue
//
// example use:
//
// override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
// {
// fixIOS9PopOverAnchor(segue)
// }
//
extension UIViewController
{
func fixIOS9PopOverAnchor(segue:UIStoryboardSegue?)
{
guard #available(iOS 9.0, *) else { return }
if let popOver = segue?.destinationViewController.popoverPresentationController,
let anchor = popOver.sourceView
where popOver.sourceRect == CGRect()
&& segue!.sourceViewController === self
{ popOver.sourceRect = anchor.bounds }
}
}
Voici un exemple d'extrait de code d'Igor Camilo dans Objective-C.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// If the sender is a UIView, we might have to correct the sourceRect of
// a potential popover being presented due to an iOS 9 bug. See:
// https://openradar.appspot.com/22095792 and http://stackoverflow.com/a/32698841/368674
if ([sender isKindOfClass:UIView.class]) {
// Fetch the destination view controller
UIViewController *destinationViewController = [segue destinationViewController];
// If there is indeed a UIPopoverPresentationController involved
if ([destinationViewController respondsToSelector:@selector(popoverPresentationController)]) {
// Fetch the popover presentation controller
UIPopoverPresentationController *popoverPresentationController =
destinationViewController.popoverPresentationController;
// Set the correct sourceRect given the sender's bounds
popoverPresentationController.sourceRect = ((UIView *)sender).bounds;
}
}
}
Voici ma solution, dans prepareForSegue
:
segue.destinationViewController.popoverPresentationController?.sourceRect = CGRectMake(anchorView.frame.size.width/2, anchorView.frame.size.height, 0, 0)
Cela déplacera le pointeur vers le bas au milieu de la vue d'ancrage
J'ai également rencontré ce problème, mais cela fonctionne maintenant lorsque je l'ai ajouté à ma PrepareForSegue Étant donné que mon identifiant Segue contient la chaîne Popover
if ([[segue identifier] containsString:@"Popover"]) {
[segue destinationViewController].popoverPresentationController.sourceRect = self.navigationItem.titleView.bounds;
}
Si vous faites référence à votre popover UIViewController
dans votre UIViewController
principale, vous pouvez ajuster la propriété sourceRect
pour compenser le popover. Par exemple, étant donné popover popoverVC
, vous pouvez faire quelque chose comme ceci:
float xOffset = 10.0;
float yOffset = 5.0;
popoverVC.popoverPresentationController.sourceRect = CGMakeRect(xOffset, yOffset, 0.0, 0.0);
Une réponse un peu plus récente pour Swift 3! Pardonner tout le casting
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popSegue" {
let popoverViewController = segue.destination
popoverViewController.popoverPresentationController?.delegate = self
segue.destination.popoverPresentationController?.sourceRect = ((sender as? UIButton)?.bounds)!
}
}
juste pour mettre à jour un exemple réel avec un code de travail pour tout UIView
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "PopoverSegueId"?:
if #available(iOS 9.0, *) {
segue.destination.popoverPresentationController?.sourceRect = (segue.destination.popoverPresentationController?.sourceView?.bounds)!
}
default:
break
}
}
Essayez de définir la largeur et la hauteur de votre ancre source (UIView ou UIBarButtonItem) et réglez-le sur actif. Définissez-le lorsque vous initialisez UIView ou UIBarButtonItem.
UIBarButtonItem
[[youruibarbuttonitem.customView.widthAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.width] setActive:YES];
[[youruibarbuttonitem.customView.heightAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.height] setActive:YES];
UIView
[[uiview.widthAnchor constraintEqualToConstant:uiview.bounds.size.width] setActive:YES];
[[uiview.heightAnchor constraintEqualToConstant:uiview.bounds.size.height] setActive:YES];