Skip to content

Instantly share code, notes, and snippets.

@briannadoubt
Last active January 25, 2023 23:25
Show Gist options
  • Save briannadoubt/6ceec84ec3943e9bc7927cbb137802a2 to your computer and use it in GitHub Desktop.
Save briannadoubt/6ceec84ec3943e9bc7927cbb137802a2 to your computer and use it in GitHub Desktop.
View + UIModalPresentationStyle
public extension View {
/// Present another SwiftUI `View` by embedding it into a `UIHostingController` and presenting it on the key `UIViewController`, on the top-most `UIWindow`.
///
/// This extension was originally copied from [this Medium article](https://medium.com/@cuongnguyenhuu/how-to-present-a-screen-with-modalpresentationstyle-in-swiftui-like-uikit-fe9b53e09d72) written by Cuon (Currie) H. NGUYEN.
///
/// The code has been updated to fix warnings and implicitly unwrapped optional variables.
/// - Parameters:
/// - isPresented: Whether or not the `Content` view is presented.
/// - modalPresentationStyle: The `UIModalPresentationStyle` to present with.
/// - content: The `Content` view that will desplay when `isPresented` is `true`.
/// - Returns: The current view.
func modal<Content: View>(
isPresented: Binding<Bool>,
style modalPresentationStyle: UIModalPresentationStyle,
@ViewBuilder content: @escaping () -> Content,
completion: (() -> Void)? = nil
) -> some View {
guard isPresented.wrappedValue else {
return self
}
UIWindow.key?.isHidden = true
let viewController = UIHostingController(rootView: content())
viewController.modalPresentationStyle = modalPresentationStyle
UIViewController.key?.present(viewController, animated: true, completion: completion)
return self
}
}
extension UIWindow {
static var key: UIWindow? {
UIApplication.shared.connectedScenes
.filter { $0.activationState == .foregroundActive }
.map { $0 as? UIWindowScene }
.compactMap { $0 }
.first?
.windows
.filter { $0.isKeyWindow }
.first
}
}
extension UIViewController {
static var key: UIViewController? {
guard
let window = UIWindow.key,
let rootViewController = window.rootViewController
else {
return nil
}
var topController = rootViewController
while let newTopController = topController.presentedViewController {
topController = newTopController
}
return topController
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment