Contacts para Swift: guía completa con ejemplos prácticos
1. ¿Qué es y para qué sirve?
El framework Contacts (Contacts.framework) es la API oficial de Apple para trabajar con la libreta de direcciones (contactos) en dispositivos iOS, macOS, watchOS y tvOS. Reemplaza al antiguo AddressBook y ofrece una interfaz moderna y orientada a objetos para acceder a los contactos del usuario. Su función principal es unificar el proceso de lectura, creación, actualización y eliminación de contactos, así como la gestión de grupos de contactos.
¿Para qué sirve? Cualquier aplicación que necesite interactuar con la agenda telefónica (mensajería, CRM, apps de llamadas, redes sociales) debe usar Contacts. El framework permite solicitar permisos de forma segura, cargar grandes volúmenes de datos de manera eficiente (mediante carga paginada y predicados) y trabajar con contactos unificados (cuando una persona se combina desde varias fuentes, como iCloud y Google).
A diferencia de las soluciones antiguas, Contacts es totalmente compatible con Swift (incluyendo async/await), utiliza CNContactStore como punto de entrada único y proporciona objetos inmutables para lectura y mutables para escritura, lo que hace que el código sea más seguro y predecible.
2. Instalación
El framework Contacts forma parte de los frameworks de sistema de Apple. No necesitas instalarlo mediante gestores de paquetes (CocoaPods, SPM o Carthage), ya está disponible en el dispositivo. Solo debes importar el módulo en tu código.
Importante: Para trabajar con contactos, debes añadir la clave NSContactsUsageDescription en el archivo Info.plist de tu proyecto. Sin esto, la aplicación fallará al intentar acceder al almacenamiento.
Comando (no es necesario, pero para claridad):
Como es un framework del sistema, no existen comandos pip, npm ni cargo. Simplemente agrega la importación en tu archivo Swift:
import Contacts
3. Inicio rápido — ejemplo mínimo funcional
Este ejemplo solicita permiso para acceder a los contactos y muestra en consola los nombres de todos los contactos de la agenda.
import Contacts
import UIKit
// 1. Crear una instancia del almacén
let store = CNContactStore()
// 2. Solicitar permiso
store.requestAccess(for: .contacts) { granted, error in
guard granted else {
print("Acceso denegado: \(error?.localizedDescription ?? "Error desconocido")")
return
}
// 3. Crear una solicitud de búsqueda
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey]
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
// 4. Ejecutar la búsqueda
do {
try store.enumerateContacts(with: request) { contact, stopPointer in
print("Contacto encontrado: \(contact.givenName) \(contact.familyName)")
}
} catch {
print("Error al obtener contactos: \(error.localizedDescription)")
}
}
4. Métodos/funciones/clases principales
4.1. CNContactStore
Firma: class CNContactStore : NSObject
Qué hace: Clase central para acceder a la base de datos de contactos. A través de ella se realizan todas las operaciones: consultas, guardado, eliminación.
Ejemplo:
let store = CNContactStore()
// Luego usamos store para todas las operaciones
4.2. requestAccess(for:completionHandler:)
Firma: func requestAccess(for entityType: CNEntityType, completionHandler: @escaping (Bool, Error?) -> Void)
Qué hace: Solicita al usuario permiso para acceder a los contactos. El primer parámetro indica el tipo de entidad (normalmente .contacts). El completionHandler recibe un booleano indicando si se concedió el acceso y un posible error.
Ejemplo:
store.requestAccess(for: .contacts) { granted, error in
if granted {
print("Permiso concedido")
} else {
print("Permiso denegado: \(error?.localizedDescription ?? "")")
}
}
4.3. enumerateContacts(with:usingBlock:)
Firma: func enumerateContacts(with fetchRequest: CNContactFetchRequest, usingBlock block: @escaping (CNContact, UnsafeMutablePointer
Qué hace: Itera sobre todos los contactos que coinciden con la solicitud de búsqueda. El bloque recibe cada contacto y un puntero para detener la iteración si es necesario.
Ejemplo:
let request = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey])
try store.enumerateContacts(with: request) { contact, stop in
print(contact.givenName)
if contact.givenName == "Juan" {
stop.pointee = true // Detener la iteración
}
}
4.4. unifiedMeContact(withKeys:)
Firma: func unifiedMeContact(withKeys keys: [CNKeyDescriptor]) throws -> CNContact
Qué hace: Devuelve el contacto unificado del usuario actual (su propia tarjeta de contacto). Es útil para aplicaciones que necesitan mostrar o editar el perfil del usuario.
Ejemplo:
do {
let meContact = try store.unifiedMeContact(withKeys: [CNContactGivenNameKey, CNContactEmailAddressesKey])
print("Mi nombre: \(meContact.givenName)")
} catch {
print("Error al obtener mi contacto: \(error)")
}
5. Conclusión
El framework Contacts de Apple es la herramienta moderna y recomendada para gestionar contactos en todas las plataformas de Apple. Con su API limpia, soporte para Swift y manejo eficiente de permisos, es la opción ideal para cualquier aplicación que necesite integrarse con la agenda del usuario. Recuerda siempre solicitar permisos y manejar los errores adecuadamente para ofrecer una experiencia de usuario fluida.
También en la biblioteca
Trabajo con YAML en C# (.NET): bibliotecas y ejemplos de uso
Migraciones de bases de datos en Node.js: Sequelize, Knex y TypeORM
Humanizer para C# (.NET): guía completa con ejemplos prácticos
Trabajo con imágenes en PHP: revisión de bibliotecas y herramientas