支持滑动以关闭工作表中显示的UIViewControllerRepresentable

时间:2020-07-24 17:43:44

标签: ios swiftui

似乎如果您使用UIViewControllerRepresentable在您的SwiftUI应用中实现视图控制器,那么当您通过sheet展示它时,就无法滑动以将其关闭。您需要做些什么来支持滑动以关闭吗?

struct ContentView: View {
    @State var showingPicker = false
    
    var body: some View {
        Text("Hello, world!")
            .onAppear {
                showingPicker = true
            }
            .sheet(isPresented: $showingPicker, content: {
                PHPicker() //cannot swipe to dismiss
                //Text("Test") //can swipe to dismiss
            })
    }
}

struct PHPicker: UIViewControllerRepresentable {
    func makeUIViewController(context: UIViewControllerRepresentableContext<PHPicker>) -> PHPickerViewController {
        let config = PHPickerConfiguration()
        return PHPickerViewController(configuration: config)
    }
    
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: UIViewControllerRepresentableContext<PHPicker>) { }
}

1 个答案:

答案 0 :(得分:1)

可能的解决方案是添加类似 handle 的东西来拖动(没有样式 - 简化演示),

demo

.sheet(isPresented: $showingPicker, content: {
        VStack {
            RoundedRectangle(cornerRadius: 8).fill(Color.gray)
                .frame(width: 60, height: 8)
                .padding(.top, 8)
            PHPicker()
        }
})

替代方案:解决方案是完全通过 UIKit 进行展示,只需在可表示的内部传递激活绑定即可。

这是一个可能的方法的演示。使用 Xcode 12.1 / iOS 14.1 测试

demo2

struct PHPickerContentView: View {
    @State var showingPicker = false
    
    var body: some View {
        Button("Picker") {
           showingPicker = true
        }
        .background(PHPicker(isPresented: $showingPicker))    // << here !!
    }
}

struct PHPicker: UIViewControllerRepresentable {
    @Binding var isPresented: Bool

    func makeUIViewController(context: Context) -> UIViewController {
        UIViewController()   // << picker presenter
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        // react on binding & show if not shown
        if isPresented && uiViewController.presentedViewController == nil {
            let config = PHPickerConfiguration()
            let picker = PHPickerViewController(configuration: config)
            picker.delegate = context.coordinator

            uiViewController.present(picker, animated: true)
            picker.presentationController?.delegate = context.coordinator
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, PHPickerViewControllerDelegate, UIAdaptivePresentationControllerDelegate {
        let owner: PHPicker
        init(_ owner: PHPicker) {
            self.owner = owner
        }

        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {

            // picked image handling code here
        
            picker.presentingViewController?.dismiss(animated: true)
            owner.isPresented = false    // << reset on action !!
        }
        
        func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
            owner.isPresented = false    // << reset on swipe !!
        }
    }
}