Present full screen modal in SwiftUI

By StartxLabs
Date 11-11-20
Present full screen modal in SwiftUI
" Present full screen modal in SwiftUI"

After the introduction of SwiftUI, it has became difficult to implement some of the features which were available in UIKit.

After iOS 13, default value of UIModalPresentationStyle has been changed to .pageSheet. Moreover, in SwiftUI, we are using .sheet instance method to present a modal. For this, we need to declare a separate State variable for enabling and disabling sheet, which can be very hectic and error-prone. 

So, to avoid this, we will be using UIkit way to present a modal. Now, the question arises, there is no concept of UIViewController in SwiftUI then how can we achieve it?


Well, we will use the Appdelegate window's rootViewController. Wait, But there is no use of Appdelegate in SwiftUI, instead we have SceneDelegate class. But it seems, SceneDelegate is using Window instance underneath. We will use below method to fetch window object.


func getWindow() -> UIWindow{
    return (UIApplication.shared.connectedScenes.first!.delegate as! SceneDelegate).window!


Now, we can easily fetch rootViewController  using getWindow().rootViewController  method.

The next hurdle is that we can present an instance of  ViewController on rootViewController. But in SwiftUI, we are using View class to represent UI. To get ViewController instance of View class we can use below method.


let viewController = UIHostingController(rootView: YOUR_VIEW_CLASS_INSTANCE)


Now, the final step is to present full screen modal of UIHostingController on rootViewController.

getWindow().rootViewController!.definesPresentationContext = true
viewController.modalPresentationStyle = .overCurrentContext
getWindow().rootViewController!.present(viewController, animated: true)

We have to change definesPresentationContext and modalPresentationStyle of parent and child viewcontroller to make the modal cover full screen.

We have accomplished our goal. Our final advice would be to put these methods in extensions or global scope so that these can be used by any class in project.

subscribe to startxlabs