LoginSignup
5
5

More than 3 years have passed since last update.

[SwiftUI]iPadでActionSheetが使えないという事実をねじ伏せる

Posted at

SwiftUIにはActionSheetというクラスがあり、文字通りUIAlertControllerのactionSheetスタイルを表示することが出来ます。
しかし、iPadではこれを使うと

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0x7fb7118d8200>) of style UIAlertControllerStyleActionSheet from _TtGC7SwiftUI19UIHostingControllerGV11SwiftUIFlux13StoreProviderV9NightfoxS8AppStateVS3_10RouterView__ (<_TtGC7SwiftUI19UIHostingControllerGV11SwiftUIFlux13StoreProviderV9NightfoxS8AppStateVS3_10RouterView__: 0x7fb711503250>). The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem.  If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'
*** First throw call stack:

というメッセージが出てクラッシュします。
このワークアラウンドとしてAlertを使うことも出来るのですが、こちらは

Alert(title: Text, primaryButton: Alert.Button, secondaryButton: Alert.Button

といった2つのボタンしか設定出来ません。

まぁでもおそらく内部的にUIAlertControllerのイニシャライザを叩いていると思うので、必ずalertスタイルにすれば行けるはずです。


extension UIAlertController {
    static func forceAlertStyle() {
        let originalSelector = #selector(UIAlertController.init(title:message:preferredStyle:))
        let swizzledSelector = #selector(UIAlertController.nfs_init(title:message:preferredStyle:))

        let originalMethod = class_getClassMethod(UIAlertController.self, originalSelector)!
        let swizzledMethod = class_getClassMethod(UIAlertController.self, swizzledSelector)!

        method_exchangeImplementations(originalMethod, swizzledMethod)
    }

    @objc class func nfs_init(title: String?, message: String?, preferredStyle: UIAlertController.Style) -> UIAlertController {
        return UIAlertController.nfs_init(title: title, message: message, preferredStyle: .alert)
    }
}

スクリーンショット 2019-11-07 1.09.04.png

こんな感じでいけました。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5