Sobes.tech
Junior

Qual é a diferença entre Keychain e User Defaults?

sobes.tech IA

Resposta da IA

UserDefaults é usado para armazenar pequenos dados não confidenciais, como configurações do utilizador ou estado da aplicação. Os dados são armazenados como pares chave-valor num ficheiro .plist e estão acessíveis a todas as partes da aplicação. UserDefaults não cifra os dados e não é adequado para armazenar informações críticas.

Keychain é usado para armazenar de forma segura dados confidenciais, como passwords, certificados, tokens e outras informações sensíveis. Os dados são cifrados e armazenados num armazenamento especializado, acessível apenas à aplicação que os gravou. Keychain é suportado ao nível do sistema operativo e fornece um alto grau de proteção de dados.

Diferenças principais:

Característica UserDefaults Keychain
Propósito Armazenamento de configurações não confidenciais Armazenamento de dados confidenciais (passwords, tokens)
Segurança Não possui cifragem incorporada Os dados são cifrados
Acesso Disponível para todas as partes da aplicação Disponível apenas para a aplicação que os gravou
Volume de dados Adequado para pequenos volumes de dados Adequado para pequenos volumes de dados confidenciais
Implementação API simples, armazenamento em ficheiro .plist API mais complexa, armazenamento no armazenamento do sistema

Exemplo de uso de UserDefaults:

// Guardar valor
UserDefaults.standard.set("dark", forKey: "theme")

// Obter valor
let theme = UserDefaults.standard.string(forKey: "theme")

Exemplo de uso de Keychain (requer trabalhar com a API SecItem ou wrappers):

// Exemplo de adição de password (simplificado, requer tratamento de erros e parâmetros adicionais)
let password = "mySecretPassword".data(using: .utf8)!
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "myAccount",
    kSecValueData as String: password
]

let statusAdd = SecItemAdd(query as CFDictionary, nil)
// Tratamento do estado

// Exemplo de obtenção de password (simplificado, requer tratamento de erros)
let queryGet: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "myAccount",
    kSecReturnData as String: kCFBooleanTrue!,
    kSecMatchLimit as String: kSecMatchLimitOne
]

var item: CFTypeRef?
let statusGet = SecItemCopyMatching(queryGet as CFDictionary, &item)

if statusGet == errSecSuccess {
    let retrievedData = item as! Data
    let retrievedPassword = String(data: retrievedData, encoding: .utf8)
    // Utilização da password
}