我正在致力于将 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() -> 也删除演示者
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([])
}
}
}
}