Estoy usando un guión segue que presenta un controlador de vista como ventana emergente. La seque tiene una costumbre de UIView como su ancla. En la pre-iOS9 la ventana emergente correctamente podría apuntar a la parte inferior central de la costumbre UIView (que se presenta a continuación el UIView). En iOS9 apunta a la esquina superior izquierda de la UIView.

Traté de hacer el seguimiento de todo el selector de llamadas a la costumbre UIView para averiguar si hay algo que puede necesitar para poner en práctica en mi personalizados UIView para proporcionar el «hotspot» de la ventana emergente, pero no podía encontrar nada

Alguna idea..? Gracias

Gracias a @Igor Camilo su respuesta – en caso de que sea de utilidad para algunos, esta es la forma en que me fijo en mi código:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

     UIPopoverPresentationController* possiblePopOver = segue.destinationViewController.popoverPresentationController;
     if (possiblePopOver != nil) {
         //
         //iOS9 -- ensure correct sourceRect
         //
         possiblePopOver.sourceRect = possiblePopOver.sourceView.bounds;
     }
    ...
 }

Ejemplo: ‘Corto’ botón activa una ventana emergente, la ventana emergente apunta a la esquina superior izquierda de ‘Ordenar’ control

iOS9 ventana emergente siempre apunta a la esquina superior izquierda de anclaje

iOS9 ventana emergente siempre apunta a la esquina superior izquierda de anclaje

  • Usted no puede utilizar UIPopoverArrowDirection constante? Todo lo demás está en desuso.
  • Hola, el problema no es la dirección, que se define correctamente en el guión gráfico segue. El problema es donde la flecha señala.
  • Así que apunta al origen y no hay manera de ajustar? ¿La flecha de ir sobre el UIView o está fuera de ella?
  • Sólo añadió un ejemplo de gif en mi pregunta anterior – se puede ver cómo la ventana emergente apunta a la esquina superior izquierda del botón Ordenar.
  • Está usted usando UIPopoverPresentationController o UIPopoverController? PresentationController tiene un sourceRect y sourceView propiedades que debería permitir ajustar el punto de anclaje.
  • Estoy usando un guión segue que presenta una ventana emergente en el iPad. Ver segunda imagen con la configuración. Esto funciona muy bien en iOS8. Sospecho que algo cambió en iOS9 y la obtención de una sourceRect desde el anclaje debe basarse en una falta selector/propiedad/lo que sea en mi costumbre UIView (el Botón de Ordenación es una costumbre UIControl).

InformationsquelleAutor Nikos | 2015-09-19

9 Comentarios

  1. 34

    Tuve exactamente el mismo problema. Acabo de resolver mediante el establecimiento de sourceRect en 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
        }
    }
    • ¿de dónde sacaste el anchorView ?
    • He actualizado Igor Camilo respuesta usando Objective-C. Esto debe responder a su pregunta, @BuntyMadan
    • En mi caso, sólo había una ventana emergente en mi controlador, así que sólo tengo el ancla de la vista de mi IBOutlets, pero creo que se puede agarrar de sender o popoverPresentationController?.sourceView. Yo no lo he probado, aunque.
    • fresco tiene su punto. gracias! +1 para los dos @IgorCamilo
    • Creo que esto debería ser anchorView.los límites, en lugar de anchorView.marco. Consulte stackoverflow.com/a/30067716/220287
  2. 18

    Tenido el mismo problema pero mi aplicación tiene una gran cantidad de pop-más de lo que he creado una función centralizada para la corrección (pero todavía tiene que usar en cada controlador de vista de que habían pop off).

    //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 }   
       }       
    }
  3. 8

    He aquí un ejemplo de Igor Camilo del fragmento de código en 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;
            }
        }
    }
    • desafortunadamente, esta solución no es adecuada para tvOS, porque no hay ninguna clase de UIPopoverPresentationController.
  4. 7

    Aquí está mi solución, dentro de prepareForSegue:

    segue.destinationViewController.popoverPresentationController?.sourceRect = CGRectMake(anchorView.frame.size.width/2, anchorView.frame.size.height, 0, 0)

    Este se mueva el puntero a la parte central inferior de la vista de anclaje

  5. 1

    También he encontrado con este problema, pero ahora funciona cuando he añadido esto a mi PrepareForSegue función. Dado que mi Segue ID contiene la cadena de ventana emergente

    if ([[segue identifier] containsString:@"Popover"]) {
        [segue destinationViewController].popoverPresentationController.sourceRect = self.navigationItem.titleView.bounds;
    }
  6. 0

    Si se hace referencia a su ventana emergente UIViewController en su principal UIViewController puede ajustar el sourceRect propiedad de desplazamiento de la ventana emergente. Por ejemplo, dada ventana emergente popoverVC puede hacer algo así:

    float xOffset = 10.0;
    float yOffset = 5.0;
    popoverVC.popoverPresentationController.sourceRect = CGMakeRect(xOffset, yOffset, 0.0, 0.0);
  7. 0

    Intenta establecer la anchura y la altura de anclaje de su fuente rect (UIView o UIBarButtonItem ) y configurarlo para que se active .Establecer cuando se está inicializando su UIView o 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];
  8. 0

    Un poco más actualizado respuesta rápida 3! Perdón a todos los 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)!
            }
        }
  9. 0

    acaba de actualizar a un ejemplo real con código de trabajo para cualquier 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
        }
    
    }

Dejar respuesta

Please enter your comment!
Please enter your name here