ActionSheet no funciona iPad

86

Estoy usando ActionSheet en mi aplicación. En mi iPhone funciona, pero no en el simulador de iPad.

este es mi código:

@IBAction func dialog(sender: AnyObject) {

    let optionMenu = UIAlertController(title: nil, message: "Choose Option", preferredStyle: .ActionSheet)
    let deleteAction = UIAlertAction(title: "Delete", style: .Default, handler: {

        (alert: UIAlertAction!) -> Void in
        println("Filtre Deleted")
    })

    let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: {
        (alert: UIAlertAction!) -> Void in
        println("Cancelled")
    })

    optionMenu.addAction(deleteAction)
    optionMenu.addAction(cancelAction)

    self.presentViewController(optionMenu, animated: true, completion: nil)
}

Y mi error:

Finalizando la aplicación debido a la excepción no detectada 'NSGenericException', motivo: 'Su aplicación ha presentado un UIAlertController () de estilo UIAlertControllerStyleActionSheet. El modalPresentationStyle de un UIAlertController con este estilo es UIModalPresentationPopover. Debe proporcionar información de ubicación para este popover a través del popoverPresentationController del controlador de alerta. Debe proporcionar sourceView y sourceRect o barButtonItem. Si esta información no se conoce cuando presenta el controlador de alerta, puede proporcionarla en el método UIPopoverPresentationControllerDelegate -prepareForPopoverPresentation '.

Stephany
fuente
Este enlace puede ayudarte.
Nimisha Patel
4
ios 8 y superior no hay una hoja de acción instancia de UIActionController u necesita establecer el tipo como UIAlertControllerStyleActionSheet .... esto puede ayudarlo .... aunque se sugiere uipopover para iPad ....
Arun
Tienes que presentarlo como un popover en iPad
Totka

Respuestas:

110

Debe proporcionar una vista de código fuente o un botón justo antes de presentar optionMenu, ya que en iPad es un UIPopoverPresentationController, como dice en su error. Esto solo significa que su hoja de acción apunta al botón que le permite al usuario saber desde dónde comenzó.

Por ejemplo, si presenta su optionMenu tocando en el elemento de la barra de navegación derecha. Podrías hacer algo como esto:

optionMenu.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem

self.presentViewController(optionMenu, animated: true, completion: nil)

o puede establecer una vista como esta: (solo necesita uno de estos 2)

optionMenu.popoverPresentationController?.sourceView = yourView

self.presentViewController(optionMenu, animated: true, completion: nil)

También tenga en cuenta que si cambia su UIAlertControllerStyle a Alerta en lugar de hoja de acción, no necesitaría especificar esto. Estoy seguro de que debe haberlo descubierto, pero solo quería ayudar a cualquiera que se encuentre con esta página.

MD Singh
fuente
30

El mismo problema para mí. Tenía un UIAlertController que funcionaba bien en el teléfono, pero fallaba en el iPad. La hoja aparece cuando se toca una celda desde una vista de tabla.

Para Swift 3, agregué 3 líneas de código justo antes de presentarlo:

        ...

        sheet.popoverPresentationController?.sourceView = self.view
        sheet.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
        sheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)


        self.present(sheet, animated: true, completion: nil)
Zach
fuente
1
Esto funcionó para mí en Swift 5.0, pero no sé cómo mostrar la ventana emergente desde la parte inferior de la vista. ¡Gracias!
Florentin Lupascu
@FlorentinLupascu: Simplemente establezca allowArrowDirections en UIPopoverArrowDirection.Down y sourceRect = CGRect (x: self.view.bounds.midX, y: self.view.bounds.bottom, width: 0, height: 0)
también el
24

Swift 3

Como se dijo anteriormente, debe configurar UIAlertController para que se presente en un punto específico en iPAD.

Ejemplo de barra de navegación:

    // 1
    let optionMenu = UIAlertController(title: nil, message: "Choose an option", preferredStyle: .actionSheet)

    // 2
    let deleteAction = UIAlertAction(title: "Option 1", style: .default, handler: {
        (alert: UIAlertAction!) -> Void in
        print("option 1 pressed")
    })
    let saveAction = UIAlertAction(title: "Option 2", style: .default, handler: {
        (alert: UIAlertAction!) -> Void in
        print("option 2 pressed")
    })

    //
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {
        (alert: UIAlertAction!) -> Void in
        print("Cancelled")
    })


    // 4

    optionMenu.addAction(deleteAction)
    optionMenu.addAction(saveAction)
    optionMenu.addAction(cancelAction)

    // 5

    optionMenu.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem

    self.present(optionMenu, animated: true) { 
        print("option menu presented")
    }
mourodrigo
fuente
8

Si desea presentarlo en el centro sin flechas [ Swift 3+ ]:

if let popoverController = optionMenu.popoverPresentationController {
        popoverController.sourceView = self.view
        popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
        popoverController.permittedArrowDirections = []
    }
self.present(optionMenu, animated: true, completion: nil)
Mohit Singh
fuente
5

agregue declaraciones en los siguientes términos antes de que se presenten.

optionMenu.popoverPresentationController.sourceView = self.view;
optionMenu.popoverPresentationController.sourceRect = 

CGRectMake(0,0,1.0,1.0);


@IBAction func dialog(sender: AnyObject) {
    ...

    optionMenu.popoverPresentationController.sourceView = self.view;
    optionMenu.popoverPresentationController.sourceRect = CGRectMake(0,0,1.0,1.0);

    self.presentViewController(optionMenu, animated: true, completion: nil)
}

funcionará bien.

Jimmy chou
fuente
Funcionó perfectamente. Lo único es que debe agregar el elemento de la barra de navegación izquierda, por lo que el menú emergente no parece que salga de la nada
Eugene Pavlov
0

Solo tenga en cuenta que también puede obtener este error si no ha vinculado la vista de origen en IB a la variable relevante en su aplicación.

Peter Johnson
fuente
0

necesitas agregar esto para Ipad

alertControler.popoverPresentationController?.sourceView = self.view

Asad Farooq
fuente