Como posso usar UserDefaults no Swift?

119

Como posso usar UserDefaults para salvar / recuperar strings, booleanos e outros dados em Swift?

Mithun Ravindran
fonte
4
Estou reabrindo esta pergunta porque pode servir como uma boa pergunta geral sobre este tópico. A resposta aceita também é mais clara do que a duplicata marcada anteriormente , que também era mais específica do que esta pergunta.
Suragch
Acho que esta questão está disponível no estouro de pilha, você deve pesquisar antes de adicionar a questão aqui
Yogesh Patel

Respostas:

329

ref: NSUserdefault objectTypes

Swift 3 e superior

Loja

UserDefaults.standard.set(true, forKey: "Key") //Bool
UserDefaults.standard.set(1, forKey: "Key")  //Integer
UserDefaults.standard.set("TEST", forKey: "Key") //setObject

Recuperar

 UserDefaults.standard.bool(forKey: "Key")
 UserDefaults.standard.integer(forKey: "Key")
 UserDefaults.standard.string(forKey: "Key")

Remover

 UserDefaults.standard.removeObject(forKey: "Key")

Remova todas as chaves

 if let appDomain = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: appDomain)
 }

Swift 2 e inferior

Loja

NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: "yourkey")
NSUserDefaults.standardUserDefaults().synchronize()

Recuperar

  var returnValue: [NSString]? = NSUserDefaults.standardUserDefaults().objectForKey("yourkey") as? [NSString]

Remover

 NSUserDefaults.standardUserDefaults().removeObjectForKey("yourkey")


Registro

registerDefaults: adiciona o registrationDictionary ao último item em cada lista de pesquisa. Isso significa que, após NSUserDefaults procurar um valor em todos os outros locais válidos, ele procurará os padrões registrados, tornando-os úteis como um valor de "fallback". Os padrões registrados nunca são armazenados entre as execuções de um aplicativo e são visíveis apenas para o aplicativo que os registra.

Os valores padrão dos arquivos de configuração padrão serão registrados automaticamente.

por exemplo, detectar o aplicativo desde o lançamento, criar a estrutura para salvar o lançamento

struct DetectLaunch {
static let keyforLaunch = "validateFirstlunch"
static var isFirst: Bool {
    get {
        return UserDefaults.standard.bool(forKey: keyforLaunch)
    }
    set {
        UserDefaults.standard.set(newValue, forKey: keyforLaunch)
    }
}
}

Registre os valores padrão no lançamento do aplicativo:

UserDefaults.standard.register(defaults: [
        DetectLaunch.isFirst: true
    ])

remova o valor no encerramento do aplicativo:

func applicationWillTerminate(_ application: UIApplication) {
    DetectLaunch.isFirst = false

}

e verifique a condição como

if DetectLaunch.isFirst {
  // app launched from first
}

Nome do conjunto UserDefaults

outro nome de suíte de propriedades , principalmente usado para o conceito de grupos de aplicativos , o cenário de exemplo que tirei daqui :

O caso de uso é que eu quero separar meus UserDefaults (diferentes lógicas de negócios podem exigir que os Userdefaults sejam agrupados separadamente) por um identificador, assim como SharedPreferences do Android. Por exemplo, quando um usuário em meu aplicativo clica no botão de logout, eu gostaria de limpar os padrões relacionados à conta, mas não a localização do dispositivo.

let user = UserDefaults(suiteName:"User")

uso de userDefaults synchronize , as informações detalhadas foram adicionadas na resposta duplicada.

Anbu.Karthik
fonte
Quando e onde você deve chamar os métodos de armazenamento? Pouco antes de o aplicativo fechar ou sempre que os valores mudam?
Josef
muito impressionante, um lugar para todos os tipos de operações.
michaeln peterson de
@ Anbu.Karthik como você atualizará o valor de uma chave em userdefaults?
sathya chinnasamy
2
@RajeshBaidya - userdefault armazena sempre apenas o valor final
Anbu.Karthik
Esses dados persistem durante a instalação / desinstalação do aplicativo?
OrangePot
40

Melhor maneira de usar UserDefaults

Passos

  1. Criar extensão de UserDefaults
  2. Crie enum com as chaves necessárias para armazenar no local
  3. Armazene e recupere os dados locais onde quiser

Amostra

extension UserDefaults{

    //MARK: Check Login
    func setLoggedIn(value: Bool) {
        set(value, forKey: UserDefaultsKeys.isLoggedIn.rawValue)
        //synchronize()
    }

    func isLoggedIn()-> Bool {
        return bool(forKey: UserDefaultsKeys.isLoggedIn.rawValue)
    }

    //MARK: Save User Data
    func setUserID(value: Int){
        set(value, forKey: UserDefaultsKeys.userID.rawValue)
        //synchronize()
    }

    //MARK: Retrieve User Data
    func getUserID() -> Int{
        return integer(forKey: UserDefaultsKeys.userID.rawValue)
    }
}

enum para chaves usadas para armazenar dados

enum UserDefaultsKeys : String {
    case isLoggedIn
    case userID
}

Salve em UserDefaults onde quiser

UserDefaults.standard.setLoggedIn(value: true)          // String
UserDefaults.standard.setUserID(value: result.User.id!) // String

Recupere dados em qualquer lugar no aplicativo

print("ID : \(UserDefaults.standard.getUserID())")
UserDefaults.standard.getUserID()

Remover Valores

UserDefaults.standard.removeObject(forKey: UserDefaultsKeys.userID) 

Desta forma, você pode armazenar dados primitivos na melhor

Atualizar Você não precisa usar synchronize () para armazenar os valores. Como @Moritz apontou que é desnecessário e deu o artigo sobre isso. Verifique os comentários para mais detalhes

iSrinivasan 27
fonte
Você não precisa synchronize(), está explicado na documentação. Não só é inútil aqui, mas pode retardar o acesso padrão.
Eric Aya
Sim, está mencionado no doc. Assim que os dados padrão forem alterados, eles serão salvos automaticamente, mas em alguns casos, seus valores podem não ser armazenados, ou seja, assíncronos. Então achei melhor sincronizar.
iSrinivasan27 de
2
Não é melhor - às vezes é até mesmo a fonte de problemas. Não use sincronização, é obsoleto e problemático. Veja codingexplorer.com/nsuserdefaults-a-swift-introduction notavelmente a parte "update". Eu também fiz muitos testes sobre isso e removi todas as chamadas para sincronizar em todos os meus aplicativos e nunca tive um problema, mesmo em situações difíceis. Mas ei, se você gosta de coisas inúteis que podem tornar seu aplicativo lento, ligue a sincronização ... claro ...;)
Eric Aya
É muito útil. Eu comentei sync (). O uso de sync () é baseado no necessário.
iSrinivasan27
hii como salvar dados em nsuserdefaults em um arquivo separado em swift
Dilip Tiwari
15

Swift 4 :

Loja

    UserDefaults.standard.set(object/value, forKey: "key_name")

Retrive

    var returnValue: [datatype]? = UserDefaults.standard.object(forKey: "key_name") as? [datatype]

Remover

    UserDefaults.standard.removeObject(forKey:"key_name") 
Nikunj Joshi
fonte
o que você quer dizer com esta linha 'UserDefaults.standard.synchronize ()' como opcional? @NikunjJoshi
Nishad Arora
2
//Save
NSUserDefaults.standardUserDefaults().setObject("yourString", forKey: "YourStringKey")

//retrive
let yourStr : AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("YourStringKey")
Dharmesh Kheni
fonte
Em Swift 3: let minutes = UserDefaults.standard.object (forKey: "minutes") as! String
Alessandro Mattiuzzi
2

Você pode usar NSUserDefaultsrapidamente desta forma,

@IBAction func writeButton(sender: UIButton)
{
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setObject("defaultvalue", forKey: "userNameKey")

}

@IBAction func readButton(sender: UIButton)
{
    let defaults = NSUserDefaults.standardUserDefaults()
    let name = defaults.stringForKey("userNameKey")
    println(name) //Prints defaultvalue in console
}
DHEERAJ
fonte
2
A primeira versão deste post dizia para usar o synchronize()comando para NSUserDefaultsgarantir que seu material seja salvo após fazer um bloco de alterações. Isso pode ter sido mais necessário no iOS 7 e anteriores, mas no iOS 8 e posterior, você não deve chamar synchronize () na maioria das situações. Verifique isto para mais informações: codingexplorer.com/nsuserdefaults-a-swift-introduction
Dharmesh Kheni
2

Swift 5 e superior:

let defaults = UserDefaults.standard

defaults.set(25, forKey: "Age")
let savedInteger = defaults.integer(forKey: "Age")

defaults.set(true, forKey: "UseFaceID")
let savedBoolean = defaults.bool(forKey: "UseFaceID")

defaults.set(CGFloat.pi, forKey: "Pi")
defaults.set("Your Name", forKey: "Name")
defaults.set(Date(), forKey: "LastRun")


let array = ["Hello", "World"]
defaults.set(array, forKey: "SavedArray")


let savedArray = defaults.object(forKey: "SavedArray") as? [String] ?? [String()

let dict = ["Name": "Your", "Country": "YourCountry"]
defaults.set(dict, forKey: "SavedDict")

let savedDictionary = defaults.object(forKey: "SavedDictionary") as? [String: String] ?? [String: String]()

:)

Xab Ion
fonte
1

Salvei o NSDictionary normalmente e consegui obtê-lo corretamente.

 dictForaddress = placemark.addressDictionary! as NSDictionary
        let userDefaults = UserDefaults.standard
        userDefaults.set(dictForaddress, forKey:Constants.kAddressOfUser)

// Para obter dados de NSDictionary.

let userDefaults = UserDefaults.standard
    let dictAddress = userDefaults.object(forKey: Constants.kAddressOfUser) as! NSDictionary
Chandni
fonte
Obrigado pela sua ajuda senhorita. :)
Venkatesh
1
class UserDefaults_WorstPresidentName {
    static let key = "appname.worstPresidentName"

    static var value: String? {
        get {
            return UserDefaults.standard.string(forKey: key)
        }
        set {
            if newValue != nil {
                UserDefaults.standard.set(newValue, forKey: key)
            } else {
                UserDefaults.standard.removeObject(forKey: key)
            }
        }
    }
}
neoneye
fonte
1

UserDefault + Helper.swift

import UIKit

private enum Defaults: String {
   case countryCode = "countryCode"
   case userloginId   = "userloginid"
}

final class UserDefaultHelper {

static var countryCode: String? {
    set{
        _set(value: newValue, key: .countryCode)
    } get {
        return _get(valueForKay: .countryCode) as? String ?? ""
    }
}

static var userloginId: String? {
    set{
        _set(value: newValue, key: .userloginId)
    } get {
        return _get(valueForKay: .userloginId) as? String ?? ""
    }
}

private static func _set(value: Any?, key: Defaults) {
    UserDefaults.standard.set(value, forKey: key.rawValue)
}

private static func _get(valueForKay key: Defaults)-> Any? {
    return UserDefaults.standard.value(forKey: key.rawValue)
}

static func deleteCountryCode() {
    UserDefaults.standard.removeObject(forKey: Defaults.countryCode.rawValue)
 }

static func deleteUserLoginId() {
    UserDefaults.standard.removeObject(forKey: Defaults.userloginId.rawValue)
 }
}

Uso:

Salvar valor:

UserDefaultHelper.userloginId = data["user_id"] as? String

Buscar valor:

let userloginid = UserDefaultHelper.userloginId

Excluir valor:

UserDefaultHelper.deleteUserLoginId()
Mannam Brahmam
fonte
1

Eu diria que a resposta da Anbu está perfeitamente bem, mas tive que adicionar guarda enquanto buscava preferências para fazer meu programa não falhar

Aqui está o recorte de código atualizado no Swift 5

Armazenamento de dados em UserDefaults

@IBAction func savePreferenceData(_ sender: Any) {
        print("Storing data..")
        UserDefaults.standard.set("RDC", forKey: "UserName") //String
        UserDefaults.standard.set("TestPass", forKey: "Passowrd")  //String
        UserDefaults.standard.set(21, forKey: "Age")  //Integer

    }

Buscando dados de UserDefaults

    @IBAction func fetchPreferenceData(_ sender: Any) {
        print("Fetching data..")

        //added guard
        guard let uName = UserDefaults.standard.string(forKey: "UserName") else { return }
        print("User Name is :"+uName)
        print(UserDefaults.standard.integer(forKey: "Age"))
    }
SwiftBoy
fonte
0

Na aula A, defina o valor da chave:

let text = "hai"  
UserDefaults.standard.setValue(text, forKey: "textValue")

Na classe B, obtenha o valor do texto usando a chave declarada na classe Ae atribua-o à respectiva variável de que você precisa:

var valueOfText  = UserDefaults.value(forKey: "textValue")
K.Gowri Manohari
fonte
0

Swift 4, usei Enum para lidar com UserDefaults.

Este é apenas um código de amostra. Você pode personalizá-lo de acordo com seus requisitos.

Para armazenar, recuperar, remover. Desta forma, basta adicionar uma chave para sua chave UserDefaults ao enum. Manipule valores ao obter e armazenar de acordo com dataType e seus requisitos.

enum UserDefaultsConstant : String {
    case AuthToken, FcmToken

    static let defaults = UserDefaults.standard


   //Store
    func setValue(value : Any) {
        switch self {
        case .AuthToken,.FcmToken:
            if let _ = value as? String {
                UserDefaults.standard.set(value, forKey: self.rawValue)
            }
            break
        }

        UserDefaults.standard.synchronize()
    }

   //Retrieve
    func getValue() -> Any? {
        switch self {
        case .AuthToken:
            if(UserDefaults.standard.value(forKey: UserDefaultsConstant.AuthToken.rawValue) != nil) {

                return "Bearer "+(UserDefaults.standard.value(forKey: UserDefaultsConstant.AuthToken.rawValue) as! String)
            }
            else {
                return ""
            }

        case .FcmToken:

            if(UserDefaults.standard.value(forKey: UserDefaultsConstant.FcmToken.rawValue) != nil) {
                print(UserDefaults.standard.value(forKey: UserDefaultsConstant.FcmToken.rawValue))
                return (UserDefaults.standard.value(forKey: UserDefaultsConstant.FcmToken.rawValue) as! String)
            }
            else {
                return ""
            }
        }
    }

    //Remove
    func removeValue() {
        UserDefaults.standard.removeObject(forKey: self.rawValue)
        UserDefaults.standard.synchronize()
    }
}

Para armazenar um valor nos padrões do usuário,

if let authToken = resp.data?.token {
     UserDefaultsConstant.AuthToken.setValue(value: authToken)
    }

Para recuperar um valor dos padrões do usuário,

//As AuthToken value is a string
    (UserDefaultsConstant.AuthToken.getValue() as! String)
Pramod More
fonte