ActionSheet nie działa na iPadzie


86

Używam ActionSheet w mojej aplikacji. Na moim iPhonie działa, ale nie na symulatorze iPada.

to jest mój kod:

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

I mój błąd:

Zakończenie aplikacji z powodu nieprzechwyconego wyjątku „NSGenericException”, powód: „Twoja aplikacja przedstawiła UIAlertController () w stylu UIAlertControllerStyleActionSheet. ModalPresentationStyle elementu UIAlertController z tym stylem to UIModalPresentationPopover. Musisz podać informacje o lokalizacji dla tego okna popover za pomocą popoverPresentationController kontrolera alertów. Musisz podać sourceView i sourceRect lub barButtonItem. Jeśli te informacje nie są znane podczas prezentowania kontrolera alertów, można je podać w metodzie UIPopoverPresentationControllerDelegate -prepareForPopoverPresentation. '


Ten link może ci pomóc.
Nimisha Patel

4
ios 8 i nowszych nie ma instancji UIActionController arkusza działania, musisz ustawić typ jako UIAlertControllerStyleActionSheet .... to może ci pomóc .... chociaż uipopover jest sugerowany dla iPada ....
Arun

Trzeba to zaprezentować jako popover na iPadzie
Totka

Odpowiedzi:


110

Musisz podać widok źródła lub przycisk tuż przed prezentacją menu opcji, ponieważ na iPadzie jest to kontroler UIPopoverPresentationController, jak mówi w twoim błędzie. Oznacza to po prostu, że arkusz akcji wskazuje przycisk, informując użytkownika, skąd się zaczął.

Na przykład, jeśli prezentujesz swoją opcję Menu, dotykając prawego elementu paska nawigacji. Możesz zrobić coś takiego:

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

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

lub możesz ustawić taki widok: (potrzebujesz tylko jednego z tych 2)

optionMenu.popoverPresentationController?.sourceView = yourView

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

Pamiętaj również, że jeśli zmienisz UIAlertControllerStyle na Alert zamiast arkusza akcji, nie musisz tego określać. Jestem pewien, że musiałeś to rozgryźć, ale chciałem tylko pomóc każdemu, kto trafi na tę stronę.


30

Dla mnie ten sam problem. Miałem kontroler UIAlertController, który działał dobrze na telefonie, ale uległ awarii na iPadzie. Arkusz pojawia się po dotknięciu komórki w widoku tabeli.

Dla Swift 3 dodałem 3 linie kodu tuż przed jego prezentacją:

        ...

        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
To zadziałało w Swift 5.0, ale nie wiem, jak wyświetlić wyskakujące okienko z dołu widoku. Dziękuję Ci!
Florentin Lupascu

@FlorentinLupascu: Po prostu ustaw allowedArrowDirections na UIPopoverArrowDirection.Down i sourceRect = CGRect (x: self.view.bounds.midX, y: self.view.bounds.bottom, width: 0, height: 0)
too

24

Szybki 3

Jak wspomniano wcześniej, należy skonfigurować UIAlertController, aby był prezentowany w określonym punkcie na iPadzie.

Przykład paska nawigacyjnego:

    // 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

Jeśli chcesz przedstawić go w środku bez strzałek [ 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

dodaj oświadczenia w następujących terminach przed przedstawieniem.

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

będzie działać dobrze.


Działał doskonale. Jedyną rzeczą jest to, że musisz dodać element lewego paska nawigacyjnego, aby menu podręczne nie wyglądało tak, jakby wychodziło znikąd
Eugene Pavlov

0

Pamiętaj, że możesz również otrzymać ten błąd, jeśli nie powiązałeś widoku źródła w IB z odpowiednią zmienną w swojej aplikacji.


0

musisz to dodać do iPada

alertControler.popoverPresentationController?.sourceView = self.view


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.