如何在 iOS 18 中直接从 UIKit 访问 SwiftUI 的 contactAccessPicker 而无需额外的视图层?

问题描述 投票:0回答:1

我正在致力于将 contactAccessPicker 集成到 UIKit 项目中。在 SwiftUI 中,该函数是 View 的扩展,因此通常这样使用:

yourView.contactAccessPicker(isPresented: $isPresented) { identifiers in 
// Fetch all contacts the app has access to.
}

我在从 UIKit 访问

contactAccessPicker
时遇到问题,因为它是
View
的扩展,因此不能直接在 UIKit 中使用。我尝试使用
UIHostingController
来呈现包含选择器的 SwiftUI 视图,但这最终会显示两个视图:

1. The initial `yourView`
2. Then `contactAccessPicker` on top of `yourView`

有没有办法直接呈现

contactAccessPicker
而不显示额外的视图层,或者在UIKit中实现这一点更有效的方法?

塞纳里奥: 当我们尝试从底部工作表选项显示联系人访问选择器时

@available(iOS 18.0, *)
struct ContactAccessPicker: View {
    @State var presented = true
    var handler: ([String]) -> ()
    
    init(completionHandler: @escaping ([String]) -> ()) {
        handler = completionHandler
    }
    
    var body: some View {
        Spacer()
            .contactAccessPicker(isPresented: $presented, completionHandler: handler).background(content: {
            Color.white
        })
    }
}

func presentPicker() {
        if #available(iOS 18.0, *) {
            let pickerView = ContactAccessPickerHostingView(completionHandler: { [weak self] ids in
                print(ids)
               DispatchQueue.main.async {
        self.contactPickerViewReference?.view.removeFromSuperview()
        self.contactPickerViewReference?.didMove(toParent: nil)
        self.contactPickerViewReference?.removeFromParent()
    }
            })
            let hostingController = UIHostingController(rootView: pickerView)
            addChild(hostingController)
            let hostingView = hostingController.view!
            hostingView.isHidden = true
            hostingView.translatesAutoresizingMaskIntoConstraints = false
            hostingView.addSubview(hView)
            hostingView.pin(to: view)
        }
    }

removeFromParent() -> 也删除演示者

ios swiftui uikit ios18
1个回答
0
投票
func presentContactAccessPicker() {
    if #available(iOS 18.0, *) {
        let pickerView = ContactAccessPickerHostingView(completionHandler: { [weak self] ids in
            guard let self else { return }
            DispatchQueue.main.async(execute: {
                guard let presentedController = self.presentedViewController, presentedController.isBeingDismissed == false else { return }
                self.dismiss(animated: true)
            })
         })
        let hostingController = UIHostingController(rootView: pickerView)
        hostingController.view.isHidden = true
        hostingController.modalPresentationStyle = .overCurrentContext
        self.present(hostingController, animated: false)
    }
}

@available(iOS 18.0, *)
struct ContactAccessPickerHostingView: View {
    @State var presented = true
    var handler: ([String]) -> ()
    
    init(completionHandler: @escaping ([String]) -> ()) {
        handler = completionHandler
    }
    
    var body: some View {
        Spacer()
            .contactAccessPicker(isPresented: $presented, completionHandler: handler)
            .onChange(of: presented) { newValue in
                if newValue == false {
                    handler([])
                }
            }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.