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

Flutter中如何跳转至iOS原生添加联系人页面

iOS Swift 唤起原生添加联系人页面实现方案

1. 前置配置

首先需要在项目的Info.plist中添加联系人写入权限声明:

配置key:NSContactsUsageDescription,值填写你需要向用户说明的权限用途,例如「需要访问通讯录以添加联系人」
如果缺失该配置,应用调用通讯录相关接口时会直接崩溃。

2. Swift 侧代码实现

需要引入系统自带的Contacts和ContactsUI框架,遵循CNContactViewControllerDelegate协议处理用户操作回调。
完整实现示例:

import UIKit
import Flutter
import Contacts
import ContactsUI

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let methodChannel = FlutterMethodChannel(name: "com.yourapp.contact_channel", binaryMessenger: controller.binaryMessenger)
    
    methodChannel.setMethodCallHandler({
      [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
      guard call.method == "openAddContactPage" else {
        result(FlutterMethodNotImplemented)
        return
      }
      self?.openAddContactPage(result: result)
    })

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  private func openAddContactPage(result: @escaping FlutterResult) {
    // 先检查通讯录权限
    let status = CNContactStore.authorizationStatus(for: .contacts)
    let contactStore = CNContactStore()
    
    if status == .notDetermined {
      contactStore.requestAccess(for: .contacts) { [weak self] granted, error in
        DispatchQueue.main.async {
          if granted {
            self?.presentAddContactController(result: result)
          } else {
            result(false)
          }
        }
      }
    } else if status == .authorized {
      presentAddContactController(result: result)
    } else {
      result(false)
    }
  }

  private func presentAddContactController(result: @escaping FlutterResult) {
    let contact = CNMutableContact()
    let addContactVC = CNContactViewController(forNewContact: contact)
    addContactVC.delegate = self
    // 用导航控制器包装后弹出
    let navController = UINavigationController(rootViewController: addContactVC)
    window?.rootViewController?.present(navController, animated: true)
    // 保存回调给后续代理方法使用
    self.addContactResult = result
  }
  
  // 定义属性存储Flutter回调
  private var addContactResult: FlutterResult?
}

// 实现CNContactViewControllerDelegate协议
extension AppDelegate: CNContactViewControllerDelegate {
  func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
    viewController.dismiss(animated: true)
    // 有contact返回代表用户点击了保存,否则是取消
    addContactResult?(contact != nil)
    addContactResult = nil
  }
  
  func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool {
    return true
  }
}

3. 注意事项

  • 代码中的通道名com.yourapp.contact_channel需要和Flutter侧调用时的通道名保持一致
  • 如果你需要给新建联系人预设字段,直接修改CNMutableContact实例的对应属性即可,比如contact.givenName = "预设名"
  • 权限申请和UI操作必须在主线程执行,否则会出现系统报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 11:30:04