概要
SwiftUIでView以外のコードからAlertを表示する方法を調べました。
最前面のViewControllerからAlertControllerをpresentすれば良さそうです。
実装
AppDelegate.swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
static var me: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
/// 最前面のViewControllerを取得する
/// https://stackoverflow.com/a/57169802/4791194
/// https://stackoverflow.com/a/42580981/4791194
func topController() -> UIViewController? {
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
var topController = keyWindow?.rootViewController
while let presentedViewController = topController?.presentedViewController {
topController = presentedViewController
}
return topController
}
}
呼び出し例
HogeViewModel.swift
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
AppDelegate.me.topController()?.present(alert, animated: true, completion: nil)
参考
- https://stackoverflow.com/questions/40991450/ios-present-uialertcontroller-on-top-of-everything-regardless-of-the-view-hier/42580981#42580981
- https://stackoverflow.com/questions/57134259/how-to-resolve-keywindow-was-deprecated-in-ios-13-0/57169802#57169802