首页 > 解决方案 > 在 SwiftUI 中呈现视图控制器

问题描述

如何使用 SwiftUI 实现以下 Objective-C 代码实现的目标?我一直无法牢牢掌握所提出的想法。

    [self presentViewController:messageViewController animated:YES completion:nil];

标签: viewswiftuipresentviewcontroller

解决方案


直到 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) // '.onClose' is a custom extension function written. you can invent your own way to call 'closeHandler'.
})

contentparameter of.uiKitFullPresent是一个以回调处理程序作为参数的闭包。您可以使用此回调来关闭呈现的视图。

到目前为止,它运作良好。不过看起来有点棘手。

如您所知,iOS 14 将为我们带来一种以您想要的方式呈现任何视图的方法。退房fullScreenCover()

关于呈现由Objective-C编写的UIViewController,正如Asperi在他的帖子中提到的那样是可能的。

更新
这是我目前使用的完整源代码。 https://gist.github.com/fullc0de/3d68b6b871f20630b981c7b4d51c8373


推荐阅读