ActionSheet не работает iPad


86

Я использую ActionSheet в своем приложении. На моем iPhone это работает, но не на симуляторе iPad.

это мой код:

@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)
}

И моя ошибка:

Завершение работы приложения из-за неперехваченного исключения «NSGenericException», причина: «Ваше приложение представило UIAlertController () стиля UIAlertControllerStyleActionSheet. ModalPresentationStyle UIAlertController с этим стилем - UIModalPresentationPopover. Вы должны предоставить информацию о местоположении для этого всплывающего окна через popoverPresentationController контроллера предупреждений. Вы должны предоставить либо sourceView и sourceRect, либо barButtonItem. Если эта информация неизвестна, когда вы представляете контроллер предупреждений, вы можете указать ее в методе UIPopoverPresentationControllerDelegate -prepareForPopoverPresentation.


Эта ссылка может вам помочь.
Nimisha Patel

4
ios 8 и более поздних версий нет экземпляра UIActionController листа действий. Вам нужно установить тип как UIAlertControllerStyleActionSheet .... это может вам помочь .... хотя для iPad предлагается uipopover ....
Арун

Вы должны представить это как всплывающее окно на iPad
Totka

Ответы:


110

Вам необходимо предоставить исходный вид или кнопку непосредственно перед представлением optionMenu, поскольку на iPad это UIPopoverPresentationController, как указано в вашей ошибке. Это просто означает, что ваш лист действий указывает на кнопку, позволяющую пользователю узнать, откуда она началась.

Например, если вы представляете свой optionMenu, нажав на элемент правой панели навигации. Вы можете сделать что-то вроде этого:

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

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

или вы можете установить такое представление: (вам просто нужен один из этих 2)

optionMenu.popoverPresentationController?.sourceView = yourView

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

Также имейте в виду, что если вы измените свой UIAlertControllerStyle на Alert вместо листа действий, вам не нужно будет это указывать. Я уверен, что вы уже догадались, но я просто хотел помочь всем, кто попадется на эту страницу.


30

У меня такая же проблема. У меня был UIAlertController, который отлично работал на телефоне, но давал сбой на iPad. Лист всплывает при нажатии на ячейку в табличном представлении.

Для Swift 3 я добавил 3 строки кода прямо перед его представлением:

        ...

        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)

1
У меня это сработало в Swift 5.0, но я не знаю, как показать всплывающее окно в нижней части представления. Спасибо!
Florentin Lupascu

@FlorentinLupascu: просто установите allowedArrowDirections в UIPopoverArrowDirection.Down и sourceRect = CGRect (x: self.view.bounds.midX, y: self.view.bounds.bottom, width: 0, height: 0)
тоже

24

Swift 3

Как было сказано ранее, вы должны настроить UIAlertController так, чтобы он отображался в определенной точке iPAD.

Пример для панели навигации:

    // 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")
    }

8

Если вы хотите разместить его в центре без стрелок [ 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)

5

перед представлением добавьте утверждения в следующих условиях.

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)
}

это будет работать хорошо.


Работает отлично. Единственное, что вам нужно добавить элемент левой панели навигации, чтобы всплывающее меню не выглядело так, будто оно появляется из ниоткуда,
Евгений Павлов

0

Обратите внимание: вы также можете получить эту ошибку, если не связали исходный код в IB с соответствующей переменной в своем приложении.



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.