0

There are possibility that, there is custom view over my controller and on which I have to show alert. So I am using below extension to present controllers on window rather than on any UIViewController.

Extension

extension UIViewController {
    func presentControllerToWindow(){
        let win = UIWindow(frame: UIScreen.main.bounds)
        let vc = UIViewController()
        vc.view.backgroundColor = .clear
        win.rootViewController = vc
        win.windowLevel = UIWindow.Level.alert + 1
        win.makeKeyAndVisible()
        vc.present(self, animated: true, completion: nil)
    }
}

Present AlertController

let alertController = UIAlertController(title: nil, message: "Select Option", preferredStyle: .alert)

alertController.presentControllerToWindow()

Issue :

The code is working fine upto swift 4.X but in swift 5.X, alert controller appears and dismissed automatically on the other second.

GIF:

  1. OpenPicker adds custom view as a subview.
  2. On clicking add file, I am presenting alertcontroller.
  3. Its automatically dismissed.

enter image description here

Edit :

I am adding my custom view like below.

extension UIView {

    func addToWindow()  {
        let window = UIApplication.shared.keyWindow!
        self.frame = window.bounds
        window.makeKeyAndVisible()
        window.windowLevel = window.windowLevel + 1
        window.addSubview(self)
    }
}

let customView = MyCustomView()
customView.addToWindow()

Now over this MyCustomView, I need to show UIAlertController

dahiya_boy
  • 9,298
  • 1
  • 30
  • 51
  • You should not touch window, You can find top View controller and directly show alert there. – Prashant Tukadiya Jan 31 '20 at 06:17
  • @PrashantTukadiya what's the problem with window? – jalone Feb 21 '22 at 11:30
  • @jalone No problem but it is not good practice - there can be scenarios like multi-window app- and there is chance to conflict with some native controls of the app - Alert view should be shown from the top most view visible in the app – Prashant Tukadiya Feb 21 '22 at 12:18

2 Answers2

3

you have to add your UIViewController view in UIApplication keyWindow

extension UIViewController {
    func presentControllerToWindow(){
        let win = UIWindow(frame: UIScreen.main.bounds)
        let vc = UIViewController()
        vc.view.backgroundColor = .clear
        win.rootViewController = vc
        win.windowLevel = UIWindow.Level.alert + 1
        win.makeKeyAndVisible()
        UIApplication.shared.keyWindow?.addSubview(vc.view) //added
        vc.present(self, animated: true, completion: nil)
    }
}
Nirav Kotecha
  • 2,493
  • 1
  • 12
  • 26
  • iOS 13 introduces new style to present a viewcontroller. To dismiss a controller user can swipe down the controller and it leads the conflicts with the image zoom feature I am using. Do you know how to handle this? – dahiya_boy Jan 31 '20 at 06:14
  • You can avoid this by using `vc.modalPresentationStyle = .fullScreen`. – palme Jan 31 '20 at 06:17
  • @palme, I tried `.fullScreen` but nothing changed. Can you please take a look -> https://i.stack.imgur.com/IudLC.gif – dahiya_boy Jan 31 '20 at 06:32
  • @dahiya_boy let me search regarding that issue. if anything i found then let you know. – Nirav Kotecha Jan 31 '20 at 06:42
  • @dahiya_boy have a look at the `vc.isModalInPresentation = true` property (https://developer.apple.com/documentation/uikit/uiviewcontroller/3229894-ismodalinpresentation) also add `#available(iOS 13.0, *)` since this is an iOS 13 feature. However it seems like you are setting the `modalPresentationStyle` for the wrong controller as the way it is displayed in your gif is wrong. – palme Jan 31 '20 at 07:48
0

I personally use the following extension to create an alert.

extension UIViewController {
  func showAlert(withTitle title: String?, message: String?) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    let action = UIAlertAction(title: "OK", style: .cancel, handler: nil)
    alert.addAction(action)
    present(alert, animated: true, completion: nil)
  }
}

It works fine with iOS 13

Hassan ElDesouky
  • 334
  • 4
  • 17
  • 1
    Yeah bcz you are adding alert on UIViewController not on window. I have a custom View over controller and my controller and 4 buttons also. – dahiya_boy Jan 31 '20 at 05:25
  • I understand now. Sorry for the confusion. Is this thread helpful? [Apple](https://forums.developer.apple.com/thread/123792) – Hassan ElDesouky Jan 31 '20 at 05:29
  • Bro your code not matching my requirement. I have edited my post, you will be more cleared about the scenario. – dahiya_boy Jan 31 '20 at 05:31
  • Check the answer [here](https://stackoverflow.com/questions/58131996/every-uialertcontroller-disappear-automatically-before-user-responds-since-ios/58133993#58133993) – Hassan ElDesouky Jan 31 '20 at 05:34
  • Hey, It is working but there is any issue. Now I have to write `(UIApplication.shared.delegate as! AppDelegate).alertWindow.isHidden = true` redundantly. I mean same extension been called from 100s time in my project and its hard to trace now from where i have to hide alertWindow. Did you know is there any callback on dismiss of alertController so that it could be managed centralized. – dahiya_boy Jan 31 '20 at 06:00