Skip to content

Instantly share code, notes, and snippets.

@pookjw
Created December 4, 2023 13:03
Show Gist options
  • Save pookjw/b288f7937769d9a00af2aad61199a1a1 to your computer and use it in GitHub Desktop.
Save pookjw/b288f7937769d9a00af2aad61199a1a1 to your computer and use it in GitHub Desktop.
import UIKit
import SwiftUI
fileprivate final class PresentedViewController: UIHostingController<AnyView> {
var key: UUID?
var willDisappear: (() -> Void)?
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isBeingDismissed && presentedViewController == nil {
willDisappear?()
}
}
}
fileprivate struct PresentableView<Content: View>: UIViewControllerRepresentable {
@Binding private var isPresented: Bool
private let modalPresentationStyle: UIModalPresentationStyle
private let content: () -> Content
@State private var didPresent = false
@State private var key: UUID = .init()
init(
isPresented: Binding<Bool>,
modalPresentationStyle: UIModalPresentationStyle,
@ViewBuilder content: @escaping () -> Content
) {
_isPresented = isPresented
self.modalPresentationStyle = modalPresentationStyle
self.content = content
}
func makeUIViewController(context: Context) -> UIViewController {
let uiViewController = UIViewController()
let contentView = uiViewController.view!
contentView.backgroundColor = .clear
contentView.isUserInteractionEnabled = false
return uiViewController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
if isPresented {
if
let hostingController = uiViewController.presentedViewController as? PresentedViewController
{
hostingController.rootView = AnyView(content())
return
}
let hostingController = PresentedViewController(rootView: AnyView(content()))
hostingController.key = key
hostingController.willDisappear = {
isPresented = false
}
hostingController.modalPresentationStyle = modalPresentationStyle
uiViewController.present(hostingController, animated: true) {
didPresent = true
}
} else {
if
didPresent,
let presentedViewController = uiViewController.presentedViewController as? PresentedViewController,
presentedViewController.key == key
{
presentedViewController.dismiss(animated: true)
}
}
}
}
extension View {
func presentWithUIKit<Content: View>(
isPresented: Binding<Bool>,
modalPresentationStyle: UIModalPresentationStyle,
@ViewBuilder content: @escaping () -> Content
) -> some View {
return overlay {
PresentableView(isPresented: isPresented, modalPresentationStyle: modalPresentationStyle, content: content)
.frame(width: .zero, height: .zero)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment