在TabView中使用VNDocumentCameraViewController作为UIViewControllerRepresentable

我有VNDocumentCameraViewController作为一个UIViewControllerRepresentable在一个名为ScanView的视图中嵌入TabView作为第二个屏幕。在取消VNDocumentCameraViewController(取消或保存扫描),我希望标签视图回到我的第一个屏幕。这部分效果很好。

我的问题是,当回到我的VNDocumentCameraViewController时,我想重新实例化那个控制器,并开始-这是我不能弄清楚如何实现。

我知道我的ContentView保持了对ScanView的引用,这就是为什么我的UIViewControllerRepresentable没有被重新实例化的原因——我如何手动做到这一点?

这是代码:

import SwiftUI
@main
struct so_VisionKitInTabsApp: App {
        var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
struct ContentView: View {
    @State private var tabSelection = 1
    var body: some View {
        TabView(selection: $tabSelection) {
            Text("First View")
                .tabItem { Text("First View") }
                .tag(1)
            ScanView(tabSelection: $tabSelection)
                .tabItem { Text("Scan View") }
                .tag(2)
        }
    }
}
import VisionKit
struct DocumentScanningViewAdapter: UIViewControllerRepresentable {
    typealias UIViewControllerType = VNDocumentCameraViewController
    let onDismiss: () -> ()
        
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    func makeUIViewController(context: Context) -> VNDocumentCameraViewController {
        let vc = VNDocumentCameraViewController()
        vc.delegate = context.coordinator
        return vc
    }
    
    func updateUIViewController(_ uiViewController: VNDocumentCameraViewController, context: Context) { }
    class Coordinator: NSObject, VNDocumentCameraViewControllerDelegate {
        var parent: DocumentScanningViewAdapter
        
        init(parent: DocumentScanningViewAdapter) {
            self.parent = parent
        }
        
        func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
            print("Finished successfully…")
            parent.onDismiss()
        }
        
        func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
            print("Cancelled…")
            resetCoordinator(for: controller)
            parent.onDismiss()
        }
        
        func resetCoordinator(for controller: VNDocumentCameraViewController) {
            controller.delegate = parent.makeCoordinator()
        }
    }
    
}
struct ScanView: View {
    @Binding var tabSelection: Int
    
    var body: some View {
        DocumentScanningViewAdapter(onDismiss: { tabSelection = 1 })
    }
}

# # #这是如何TabView works: it saves s工作:它保存每个TAB的状态

你可以破解它,但请不要这么做:当iOS用户看到标签视图时,他希望如果他从一个标签切换到另一个标签,并返回,他不会失去任何状态

相反,你只需创建一个按钮,将你的文档选择器显示为。sheet(…)或使用NavigationLink在导航控制器中push,你的问题就会消失。

如果你使用其中一种方法,你不需要重置控制器的状态因为每次你呈现一个视图时,它都会被重新创建

如果你仍然想那样做,你可以用UINavigationController包装你的控制器并在updateUIViewController中初始化你自己的控制器

func makeUIViewController(context: Context) -> UINavigationController {
    let controller = UINavigationController()
    controller.isNavigationBarHidden = true
    return controller
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
    let vc = VNDocumentCameraViewController()
    vc.delegate = context.coordinator
    uiViewController.viewControllers = [vc]
}

updateUIViewController在每次需要视图重新渲染时被调用。如果使用TabView,它仍然不能工作,因为状态被保存了,你可以添加。id(tabSelection)到你的ScanView

感谢上面Philip的回答,建议我可以使用.sheet I came up with this new ScanView which uses a <我想出了这个新的ScanView which uses a .full它使用一个.fullScreenCover.

做这项工作,但它将覆盖标签栏(我认为我可以生活)。

struct ScanView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @State private var showFullscreen = true
    @Binding var tabSelection: Int
    
    var body: some View {
        EmptyView()
            .fullScreenCover(isPresented: $showFullscreen, onDismiss: {
                presentationMode.wrappedValue.dismiss()
            }) {
                DocumentScanningViewAdapter(onDismiss: {
                    showFullscreen = false
                    tabSelection = 1
                })
            }
            .onAppear {
                showFullscreen = true
            }
    }
}
阅读全文

▼ 版权说明

相关文章也很精彩
推荐内容
更多标签
相关热门
全站排行
随便看看

错说 cuoshuo.com —— 程序员的报错记录

部分内容根据CC版权协议转载;网站内容仅供参考,生产环境使用务必查阅官方文档

辽ICP备19011660号-5

×

扫码关注公众号:职场神器
发送: 1
获取永久解锁本站全部文章的验证码