在SwiftUI中呈现新视图

CH *_*ing 5 ios swiftui

我想单击一个按钮,然后像present modally在UIKit中 一样呈现一个新视图在此处输入图片说明

我已经看过“ 如何使用图纸呈现新视图 ”,但是我不想将其作为模式图纸附加到主视图。

而且我不想使用NavigationLink,因为我不希望新视图和旧视图具有导航关系。

谢谢你的帮助...

Moj*_*ini 49

显示模态(iOS 13 风格)

你只需要一个sheet能够自我解除的简单:

struct ModalView: View {
    @Binding var presentedAsModal: Bool
    var body: some View {
        Button("dismiss") { self.presentedAsModal = false }
    }
}
Run Code Online (Sandbox Code Playgroud)

并将其呈现为:

struct ContentView: View {
    @State var presentingModal = false
    
    var body: some View {
        Button("Present") { self.presentingModal = true }
        .sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我将 传递presentingModal给模态,因此您可以从模态本身中消除它,但您可以摆脱它。


让它真正存在fullscreen(不仅仅是视觉上)

您需要访问ViewController. 所以你需要一些辅助容器和环境的东西:

struct ViewControllerHolder {
    weak var value: UIViewController?
}

struct ViewControllerKey: EnvironmentKey {
    static var defaultValue: ViewControllerHolder {
        return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)

    }
}

extension EnvironmentValues {
    var viewController: UIViewController? {
        get { return self[ViewControllerKey.self].value }
        set { self[ViewControllerKey.self].value = newValue }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么你应该使用实现这个扩展:

extension UIViewController {
    func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
        let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
        toPresent.modalPresentationStyle = style
        toPresent.rootView = AnyView(
            builder()
                .environment(\.viewController, toPresent)
        )
        NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "dismissModal"), object: nil, queue: nil) { [weak toPresent] _ in
            toPresent?.dismiss(animated: true, completion: nil)
        }
        self.present(toPresent, animated: true, completion: nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

最后

你可以让它fullscreen像:

struct ContentView: View {
    @Environment(\.viewController) private var viewControllerHolder: UIViewController?
    
    var body: some View {
        Button("Login") {
            self.viewControllerHolder?.present(style: .fullScreen) {
                Text("Main") // Or any other view you like
// uncomment and add the below button for dismissing the modal
            // Button("Cancel") {
            //       NotificationCenter.default.post(name: Notification.Name(rawValue: "dismissModal"), object: nil)
            //        }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sou*_*ean 9

对于 iOS 14 和 Xcode 12:

struct ContentView: View {
    @State private var isPresented = false

var body: some View {
    Button("Show Modal with full screen") {
        self.isPresented.toggle()
    }
    .fullScreenCover(isPresented: $isPresented, content: FullScreenModalView.init)
    }
}
Run Code Online (Sandbox Code Playgroud)
struct FullScreenModalView: View {
     @Environment(\.presentationMode) var presentationMode

var body: some View {
    VStack {
        Text("This is a modal view")
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(Color.red)
    .edgesIgnoringSafeArea(.all)
    .onTapGesture {
        presentationMode.wrappedValue.dismiss()
    }
}
}
Run Code Online (Sandbox Code Playgroud)

希望这个回答能帮到大家!在下面评论你的结果。

参考:此链接