Contacts Swift: guía completa con ejemplos prácticos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

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) -> Void) throws

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.

Recommendations