Posted at

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

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

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