-
-
Save timothycosta/a43dfe25f1d8a37c71341a1ebaf82213 to your computer and use it in GitHub Desktop.
struct ViewControllerHolder { | |
weak var value: UIViewController? | |
init(_ value: UIViewController?) { | |
self.value = value | |
} | |
} | |
struct ViewControllerKey: EnvironmentKey { | |
static var defaultValue: ViewControllerHolder { return ViewControllerHolder(UIApplication.shared.windows.first?.rootViewController ) } | |
} | |
extension EnvironmentValues { | |
var viewController: ViewControllerHolder { | |
get { return self[ViewControllerKey.self] } | |
set { self[ViewControllerKey.self] = newValue } | |
} | |
} | |
extension UIViewController { | |
func present<Content: View>(presentationStyle: UIModalPresentationStyle = .automatic, transitionStyle: UIModalTransitionStyle = .coverVertical, animated: Bool = true, completion: @escaping () -> Void = {}, @ViewBuilder builder: () -> Content) { | |
let toPresent = UIHostingController(rootView: AnyView(EmptyView())) | |
toPresent.modalPresentationStyle = presentationStyle | |
toPresent.rootView = AnyView( | |
builder() | |
.environment(\.viewController, ViewControllerHolder(toPresent)) | |
) | |
if presentationStyle == .overCurrentContext { | |
toPresent.view.backgroundColor = .clear | |
} | |
self.present(toPresent, animated: animated, completion: completion) | |
} | |
} |
Thanks for this! I have a couple of questions
Is there a way to make the modal only as big as the content you put in it? I don’t want the white box that appears when using .formSheet/pageSheet. (I know I can just set toPresent.view.backgroundColor = .clear
) preferredContentSize
seems like an option but haven’t had a chance to test
Also when I tried to add a button to the body of ModalContentView to dismiss (experimenting with full screen), the button appeared behind the content, not above it like I expected given its a VStack. I can’t therefore see how to dismiss full screen
@Environment(\.viewController) private var viewControllerHolder: ViewControllerHolder?
private var viewController: UIViewController? {
self.viewControllerHolder?.value
}
with this code I'm getting error like
Key path value type 'ViewControllerHolder' cannot be converted to contextual type 'ViewControllerHolder?
@Environment(\.viewController) private var viewControllerHolder: ViewControllerHolder? private var viewController: UIViewController? { self.viewControllerHolder?.value }
with this code I'm getting error like
Key path value type 'ViewControllerHolder' cannot be converted to contextual type 'ViewControllerHolder?
Don't have time to test this but maybe try:
@Environment(\.viewController) private var viewControllerHolder: ViewControllerHolder
private var viewController: UIViewController? {
self.viewControllerHolder.value
}
Reading the gist, Line 14 defines viewController
to return a non-optional ViewControllerHolder
so I'm guessing that's the issue you're running into.
and how to dismiss it
its support for RTL?
Using UIViewControllerRepresentable to manage the make/update lifetime will fix the leak.
Thanks! As you said it's just a compiler issue! I've just changed it to:
The memory leak is gone as well! Thanks again!