How to Use Userdefaults in Swift

How can I use UserDefaults in Swift?

ref: NSUserdefault objectTypes

Swift 3 and above

Store

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

Retrieve

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

Remove

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

Remove all Keys

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

Swift 2 and below

Store

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

Retrieve

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

Remove

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


Register

registerDefaults: adds the registrationDictionary to the last item in every search list. This means that after NSUserDefaults has looked for a value in every other valid location, it will look in registered defaults, making them useful as a "fallback" value. Registered defaults are never stored between runs of an application, and are visible only to the application that registers them.

Default values from Defaults Configuration Files will automatically be registered.

for example detect the app from launch , create the struct for save launch

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

Register default values on app launch:

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

remove the value on app termination:

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

}

and check the condition as

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

UserDefaults suite name

another one property suite name, mostly its used for App Groups concept, the example scenario I taken from here :

The use case is that I want to separate my UserDefaults (different business logic may require Userdefaults to be grouped separately) by an identifier just like Android's SharedPreferences. For example, when a user in my app clicks on logout button, I would want to clear his account related defaults but not location of the the device.

let user = UserDefaults(suiteName:"User")

use of userDefaults synchronize, the detail info has added in the duplicate answer.

How to use Userdefaults to store UItableview data in swift?

Yes, we can store in UserDefaults, But it is not flexible as compare to Core Data or other storage for add, updates or delete operations.

Below code supposed to work.

You need to make "CartStruct" as Codable

struct CartStruct : Codable {
var cartItems: jsonstruct
var cartQuantity: Int
}

Next, Add this to insert and store it in tap "addToCartbtnTapped" .(DetailViewController)

 func saveCart(data: CartStruct) {
let defaults = UserDefaults.standard
if let cdata = defaults.data(forKey: "cartt") {
var cartArray = try! PropertyListDecoder().decode([CartStruct].self, from: cdata)
cartArray.append(data)
cartCount.text = "\(cartArray.count)"
if let updatedCart = try? PropertyListEncoder().encode(cartArray) {
UserDefaults.standard.set(updatedCart, forKey: "cartt")
}
}
}

@IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
addToCartbtn.isUserInteractionEnabled = false
}
}


@IBAction func cartTappedToNavigate(_ sender: Any) {
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}

Now, Fetch your cart data from where you stored.(CartViewController)

override func viewDidLoad() {
super.viewDidLoad()
self.getCartData()
}

func getCartData() {
let defaults = UserDefaults.standard
if let data = defaults.data(forKey: "cartt") {
cartArray = try! PropertyListDecoder().decode([CartStruct].self, from: data)
cartTableView.reloadData()
}
}

How to store date in userdefaults?

If you only want to display the date value you can convert and store it as string otherwise you convert/format it after you have read it, either way you should make sure you use the same type when saving and reading

//save as Date
UserDefaults.standard.set(Date(), forKey: key)

//read
let date = UserDefaults.standard.object(forKey: key) as! Date
let df = DateFormatter()
df.dateFormat = "dd/MM/yyyy HH:mm"
print(df.string(from: date))

// save as String
let df = DateFormatter()
df.dateFormat = "dd/MM/yyyy HH:mm"
let str = df.string(from: Date())
UserDefaults.standard.setValue(str, forKey: key)

// read
if let strOut = UserDefaults.standard.string(forKey: key) {
print(strOut)
}

Best approach to use UserDefaults

In didSet of tasks array, you can simply set the current array elements in UserDefaults.

struct Task: Codable {
let taskName: String
let isCompleted: Bool
}

var tasks = [Task]() {
didSet {
let data = try? JSONEncoder().encode(tasks)
UserDefaults.standard.set(data, forKey: "ToDoDataKey")
}
}

func addItem(itemName: String, isCompleted: Bool = false) {
tasks.append(Task(taskName: itemName, isCompleted: isCompleted))
}

This will ensure that the data in UserDefaults is synchronized with that currently in the memory.

And fetch the data only in viewDidLoad() where the data will be loaded for the first time.

func fetchTasks() -> [Task] {
if let data = UserDefaults.standard.data(forKey: "ToDoDataKey"), let tasks = try? JSONDecoder().decode([Task].self, from: data) {
return tasks
}
return []
}

Call fetchTasks() in viewDidLoad().

UserDefaults How can I get my own saved keys?

You cannot "get" from user defaults just the keys for user defaults entries that you created in code. What's in your user defaults is what's in your user defaults; it doesn't have any way of distinguishing "who" created a particular entry.

Knowing the keys you added is your business. Typically this information is hard-coded into your app, e.g. you have a list of constants, usually as static properties of an enum or struct. If you are creating keys dynamically, then if you need to know the names of the keys you created, storing that information is entirely up to you.

How to do signin / signup and logout navigation using userdefaults in swift?

In signinVC add the following line in viewDidLoad

if UserDefaults.standard.bool(forKey: "USER_LOGIN"){
//navigate to home page
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
navigationController?.pushViewController(vc, animated: true)
}
}

Modify signupVC like following

class RegisterViewController: UIViewController {
@IBOutlet weak var firstNameTextfield: UITextField!
@IBOutlet weak var lastNameTextfield: UITextField!
@IBOutlet weak var emailTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!


var userDict : Dictionary<String,UserData>?

@IBAction func registerBtnClicked(_ sender: Any) {

if firstNameTextfield.text?.isEmpty == true{
self.showAlert(title: "Registration", message: "please enter first name")

}
else if lastNameTextfield.text?.isEmpty == true{
self.showAlert(title: "Registration", message: "please enter last name")

}else if emailTextfield.text?.isEmpty == true{
self.showAlert(title: "Registration", message: "please enter email")

}else if passwordTextfield.text?.isEmpty == true{
self.showAlert(title: "Registration", message: "please enter password")

}
else{
self.userDict = UserDefaults.standard.dictionary(forKey: "UserList") as! Dictionary<String, RegisterViewController.UserData>

let userData = UserData(userName: firstNameTextfield.text, lastName: lastNameTextfield.text, email: emailTextfield.text, userPassword: passwordTextfield.text)
self.userDict[firstNameTextfield.text] = userData

UserDefaults.standard.setValue(self.userDict, forKey: "UserList")

DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
navigationController?.pushViewController(vc, animated: true)
}


}
}

struct UserData {
var userName : String
var lastName : String
var email : String
var userPassword : String
}

Finally modify loginBtnClicked method as following

@IBAction func loginBtnClicked(_ sender: Any) {

let userDict = UserDefaults.standard.dictionary(forKey: "UserList") as! Dictionary<String, UserData>

guard let usrData = userDict[userNameTextfield.text] as! UserData else {
// no user registered with this user name
return
}

if usrData.userPassword == passwordTextfield.text {
// login successfull
UserDefaults.standard.set(true, forKey: "USER_LOGIN")
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
navigationController?.pushViewController(vc, animated: true)
}

}else{
//login failed
showAlert(title: "LogIn", message: "please enter username and password")
}

}


Related Topics



Leave a reply



Submit