Contacts para Swift: guia completo com exemplos
1. O que é e para que serve
O framework Contacts (Contacts.framework) é a API oficial da Apple para gerenciar a agenda de contatos em dispositivos iOS, macOS, watchOS e tvOS. Ele substituiu o antigo AddressBook e oferece uma interface moderna e orientada a objetos para acessar os contatos do usuário. O principal objetivo é unificar o processo de leitura, criação, atualização e exclusão de contatos, além de gerenciar grupos de contatos.
Por que usar? Qualquer aplicativo que precise interagir com a agenda telefônica (mensageiros, sistemas CRM, apps de chamadas, redes sociais) deve utilizar o Contacts. O framework permite solicitar permissões de forma segura, carregar grandes volumes de dados com eficiência (através de carregamento paginado e predicados) e trabalhar com contatos unificados (quando uma mesma pessoa é mesclada de várias fontes, como iCloud e Google).
Diferente das soluções antigas, o Contacts tem suporte total ao Swift (incluindo async/await), utiliza o CNContactStore como ponto de entrada único e fornece objetos imutáveis para leitura e mutáveis para escrita, tornando o código mais seguro e previsível.
2. Instalação
O framework Contacts faz parte dos frameworks de sistema da Apple. Você não precisa instalá-lo via gerenciadores de pacotes (CocoaPods, SPM ou Carthage) — ele já está disponível no dispositivo. Basta importar o módulo no seu código.
Importante: Para trabalhar com contatos, é necessário adicionar a chave NSContactsUsageDescription no arquivo Info.plist do seu projeto. Sem isso, o aplicativo será encerrado ao tentar acessar o armazenamento.
Comando (não necessário, mas para clareza):
Como é um framework do sistema, não existem comandos pip, npm ou cargo. Basta adicionar o import no arquivo Swift:
import Contacts
3. Início rápido — exemplo mínimo funcional
Este exemplo solicita permissão para acessar os contatos e exibe no console os nomes de todos os contatos da agenda.
import Contacts
import UIKit
// 1. Cria uma instância do armazenamento
let store = CNContactStore()
// 2. Solicita permissão
store.requestAccess(for: .contacts) { granted, error in
guard granted else {
print("Acesso negado: \(error?.localizedDescription ?? "Erro desconhecido")")
return
}
// 3. Cria a requisição de busca
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey]
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
// 4. Executa a busca
do {
try store.enumerateContacts(with: request) { contact, stopPointer in
print("Contato encontrado: \(contact.givenName) \(contact.familyName)")
}
} catch {
print("Erro ao obter contatos: \(error.localizedDescription)")
}
}
4. Principais métodos/funções/classes
4.1. CNContactStore
Assinatura: class CNContactStore : NSObject
O que faz: Classe central para acessar o banco de dados de contatos. Todas as operações (consultas, salvamento, exclusão) são realizadas através dela.
Exemplo:
let store = CNContactStore()
// Em seguida, use store para todas as operações
4.2. requestAccess(for:completionHandler:)
Assinatura: func requestAccess(for entityType: CNEntityType, completionHandler: @escaping (Bool, Error?) -> Void)
O que faz: Solicita ao usuário permissão para acessar contatos. O parâmetro entityType deve ser .contacts. O completion handler retorna um booleano indicando se a permissão foi concedida e um possível erro.
Exemplo:
store.requestAccess(for: .contacts) { granted, error in
if granted {
print("Permissão concedida!")
} else {
print("Permissão negada: \(error?.localizedDescription ?? "")")
}
}
4.3. enumerateContacts(with:using:)
Assinatura: func enumerateContacts(with fetchRequest: CNContactFetchRequest, using block: (CNContact, UnsafeMutablePointer
O que faz: Itera sobre todos os contatos que correspondem ao fetch request. O bloco é chamado para cada contato encontrado. Você pode interromper a iteração definindo stopPointer.pointee = true.
Exemplo:
let request = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey])
try store.enumerateContacts(with: request) { contact, stop in
print(contact.givenName)
if contact.givenName == "João" {
stop.pointee = true // Para a iteração
}
}
4.4. unifiedContacts(matching:keysToFetch:)
Assinatura: func unifiedContacts(matching predicate: NSPredicate, keysToFetch keys: [CNKeyDescriptor]) throws -> [CNContact]
O que faz: Retorna contatos unificados que correspondem a um predicado. Útil para buscar contatos específicos por identificador ou por outros critérios.
Exemplo:
let predicate = CNContact.predicateForContacts(matchingName: "Maria")
let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: [CNContactGivenNameKey, CNContactFamilyNameKey])
for contact in contacts {
print("\(contact.givenName) \(contact.familyName)")
}
5. Considerações finais
O framework Contacts é essencial para qualquer aplicativo iOS que precise interagir com a agenda do usuário. Com ele, você pode ler, criar, atualizar e excluir contatos de forma segura e eficiente. Lembre-se sempre de solicitar permissão antes de acessar os dados e de tratar possíveis erros, como permissão negada ou falhas de busca.
Também na biblioteca
Cliente OAuth para Java: ScribeJava e Spring Security OAuth2
Geração de PDF em Java: visão geral das bibliotecas iText, Apache PDFBox, OpenPDF
Geração Swagger/OpenAPI para Rust: biblioteca Utoipa