SwiftUI模式视图



从任何类或结构模式显示SwiftUI视图的最佳方式是什么?我使用UIKit中的UIHostingController。有没有更好的方法可以只使用SwiftUI来做到这一点?

ContentView,带有显示SwiftUI视图的按钮

struct ContentView: View {
var body: some View {
Button {
//  Present the view
presentView(controller: UIHostingController(rootView: view))
} label: {
Text("Present view")
}
}

var view: some View {
Button {
//  Dismiss the view
dismissView()
} label: {
Rectangle()
.overlay(
Text("Dismiss view")
)
}
}
}

用于显示SwiftUI视图的功能

extension ContentView {
//  Returns the top view controller
func topViewController() -> UIViewController? {
let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
if var topController = keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController { topController = presentedViewController }
return topController
} else { return nil }
}

//  Presents the SwiftUI view in a UIHostingController
func presentView(controller: UIViewController) {
controller.view.backgroundColor = .none
controller.modalPresentationStyle = .overCurrentContext
topViewController()?.present(controller, animated: false, completion: nil)
}

//  Removes the UIHostingViewController from root view
func dismissView() {
topViewController()?.dismiss(animated: false, completion: nil)
}
}

您可以这样呈现模式表:

struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Present") { 
showSheet.toggle() 
}.font(.largeTitle)
.sheet(isPresented: $showSheet) { 
SheetView() 
}
}
}
struct SheetView: View {
@Environment(.dismiss) var dismiss
var body: some View {
ZStack {
Button { 
dismiss() 
} label: {
Image(systemName: "xmark.circle")
.font(.largeTitle)
.foregroundColor(.gray)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
.padding()
}
}

或者像这样在全屏上呈现模态:

struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Present") { 
showSheet.toggle() 
}.font(.largeTitle)
.fullScreenCover(isPresented: $showSheet) {
SheetView()
}
}
}

struct SheetView: View {
@Environment(.presentationMode) var presentationMode

var body: some View {

ZStack {
Button { 
presentationMode.wrappedValue.dismiss() 
} label: {
Image(systemName: "xmark.circle")
.font(.largeTitle)
.foregroundColor(.gray)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) 
.padding()
}
}

对于您的评论,这没有问题,您可以这样做:

struct ContentView: View {
@State private var showSheet = false
var body: some View {
ZStack {
Button("Present") {
showSheet.toggle()
}
.font(.largeTitle)

if showSheet {
ZStack {
Button {
showSheet.toggle()
} label: {
Image(systemName: "xmark.circle")
.font(.largeTitle)
.foregroundColor(.gray)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
.padding()
}
.background(.ultraThickMaterial)
}
}
}
}

最新更新