在iOS 13.x之前,SwiftUI没有提供相应的方法。因为我也有同样的需求,所以编写了一个自定义的View修饰符来实现它。
extension View {
func uiKitFullPresent<V: View>(isPresented: Binding<Bool>, style: UIModalPresentationStyle = .fullScreen, content: @escaping (_ dismissHandler: @escaping () -> Void) -> V) -> some View {
self.modifier(FullScreenPresent(isPresented: isPresented, style: style, contentView: content))
}
}
struct FullScreenPresent<V: View>: ViewModifier {
@Binding var isPresented: Bool
@State private var isAlreadyPresented: Bool = false
let style: UIModalPresentationStyle
let contentView: (_ dismissHandler: @escaping () -> Void) -> V
@ViewBuilder
func body(content: Content) -> some View {
if isPresented {
content
.onAppear {
if self.isAlreadyPresented == false {
let hostingVC = UIHostingController(rootView: self.contentView({
self.isPresented = false
self.isAlreadyPresented = false
UIViewController.topMost?.dismiss(animated: true, completion: nil)
}))
hostingVC.modalPresentationStyle = self.style
UIViewController.topMost?.present(hostingVC, animated: true) {
self.isAlreadyPresented = true
}
}
}
} else {
content
}
}
}
而且,您可以按以下方式使用它。
.uiKitFullPresent(isPresented: $isShowingPicker, content: { closeHandler in
SomeFullScreenView()
.onClose(closeHandler)
})
.uiKitFullPresent
的
content
参数是一个闭包,它有一个回调处理程序作为其参数。您可以使用此回调来关闭呈现的视图。
到目前为止,它一直表现良好。不过看起来有点棘手。
正如您所知,iOS 14将为我们带来以任何您想要的方式呈现任何视图的方法。请查看
fullScreenCover()
。
关于呈现由Objective-C编写的UIViewController,正如Asperi在他的博客中提到的那样,这是可能的。
更新:
这是我目前正在使用的完整源代码。
https://gist.github.com/fullc0de/3d68b6b871f20630b981c7b4d51c8373
更新2:
现在,我想说这不是一个好的方法,因为潜在的思路似乎与SwiftUI机制并不匹配。
UIViewRepresentable
,有很多教程展示了如何在 SwiftUI 中使用 UIKit 视图和视图控制器。 - Andrew