You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIKit中通过UIHostingController调用contactAccessPicker避免双重弹窗

在UIKit中直接展示iOS18的ContactAccessPicker(避免双重弹窗)

要解决双重弹窗问题,核心是让承载SwiftUI的UIHostingController完全不可见,仅触发系统原生的contactAccessPicker。以下是简洁的实现方案:

步骤1:创建SwiftUI包装视图

该视图无任何可见内容,仅用于触发和管理联系人选择器:

import SwiftUI

struct ContactAccessPickerWrapper: View {
    @State private var isPickerPresented = true
    let selectionHandler: ([String]) -> Void
    let dismissHandler: () -> Void
    
    var body: some View {
        EmptyView()
            .contactAccessPicker(isPresented: $isPickerPresented) { identifiers in
                selectionHandler(identifiers)
                dismissHandler()
            }
            .onChange(of: isPickerPresented) { isActive in
                if !isActive {
                    dismissHandler()
                }
            }
    }
}

步骤2:在UIKit中调用展示

在你的UIKit视图控制器中,添加触发逻辑(例如绑定到导航栏按钮的点击事件):

import UIKit
import SwiftUI

class YourViewController: UIViewController {
    lazy var addContactButton: UIBarButtonItem = {
        let button = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(showContactPicker))
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.rightBarButtonItem = addContactButton
    }
    
    @objc private func showContactPicker() {
        let pickerWrapper = ContactAccessPickerWrapper(
            selectionHandler: { selectedIdentifiers in
                // 处理选中的联系人标识符
                print("选中的联系人ID:\(selectedIdentifiers)")
                self.fetchContacts(with: selectedIdentifiers)
            },
            dismissHandler: {
                self.dismiss(animated: true)
            }
        )
        
        let hostingController = UIHostingController(rootView: pickerWrapper)
        hostingController.modalPresentationStyle = .overFullScreen
        hostingController.view.backgroundColor = .clear
        
        present(hostingController, animated: false)
    }
    
    private func fetchContacts(with identifiers: [String]) {
        // 你的联系人获取逻辑
    }
}

方案说明

  • 消除双重弹窗:UIHostingController的视图为透明的EmptyView,用户只会看到系统原生的联系人选择器。
  • 自动资源清理:无论用户选择联系人还是取消操作,都会触发回调销毁UIHostingController,避免内存泄漏。
  • 简化状态管理:利用SwiftUI的@State自动触发选择器展示,无需额外的跨框架状态同步逻辑。

注意事项

  • 必须将modalPresentationStyle设置为.overFullScreen或.overCurrentContext,否则UIHostingController会替换当前视图栈导致异常。
  • 弹出时关闭动画(animated: false),避免不必要的视觉闪烁。

内容的提问来源于stack exchange,提问作者Z S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:43:09