How to use NSUserDefaults to store an array of dictionaries - arrays

Trying to store an array of dictionaries with NSUserDefaults.
var theTasks: [[String:Any]] = [["num":1,"title":"example","colour":"red"]]
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(theTasks, forKey: "myTasks")
defaults.synchronize()
let selected = theTasks[1]
Gives error:
Cannot convert value of type '[[String:Any]]' to expected argument of type 'AnyObject?'

Swift 3.x
In Swift 3 it has changed so now it needs to be saved as [Any] Any Array and use UserDefaults array(forKey:) method to load it:
let theTasks: [Any] = [["num": 1, "title": "example", "colour": "red"]]
UserDefaults.standard.set(theTasks, forKey: "myTasks")
if let loadedTasks = UserDefaults.standard.array(forKey: "myTasks") as? [[String: Any]] {
print(loadedTasks)
}
var theTasks: [[String: Any]] {
get {
return UserDefaults.standard.array(forKey: "myTasks") as? [[String: Any]] ?? []
}
set {
UserDefaults.standard.set(newValue as [Any], forKey: "myTasks")
}
}
Swift 2.x
You just need to save it as a AnyObject array and use NSUserDefaults method arrayForKey to load it:
let theTasks: [AnyObject] = [["num": 1, "title": "example", "colour": "red"]]
NSUserDefaults.standardUserDefaults().setObject(theTasks, forKey: "myTasks")
if let loadedTasks = NSUserDefaults.standardUserDefaults().arrayForKey("myTasks") as? [[String: AnyObject]] {
print(loadedTasks)
}
You can also create a computed property with a getter and a setter to do all the work behind the scenes for you as follow:
var theTasks: [[String: AnyObject]] {
get {
return NSUserDefaults.standardUserDefaults().arrayForKey("myTasks") as? [[String: AnyObject]] ?? []
}
set {
NSUserDefaults.standardUserDefaults().setObject(newValue as [AnyObject], forKey: "myTasks")
}
}
print(theTasks) // [["title": example, "colour": red, "num": 1]]
theTasks[0]["title"] = "another example"
print(theTasks) // [["title": another example, "colour": red, "num": 1]]

Just call the .setObject() method directly from NSUserDefaults()and it should work fine.
NSUserDefaults().setObject(theTasks, forKey: "myTasks")

Related

How to add data inside two arrays inside for loop

I'm trying to add data to array inside for loop and again to array in another for loop.
Its working on first for loo, but in second data is empty. How to fix that
This is how it currently looks inside firestore and you can see scores missing.
this is code:
func updateCourseData() {
var data = ["endTime": Timestamp(date: Date()),
"players": []] as [String : Any]
for i in 0..<players.count {
var playerData = ["playerId": games[i].id,
"scores": []] as [String : Any]
var existingItems = data["players"] as? [[String: Any]] ?? [[String: Any]]()
existingItems.append(playerData)
data["players"] = existingItems
for score in 0..<selectedPage + 1 {
let scoreData = ["hole": games[i].scores[score].hole,
"score": games[i].scores[score].score] as [String : Any]
var existingScores = playerData["scores"] as? [[String: Any]] ?? [[String: Any]]()
existingScores.append(scoreData)
playerData["scores"] = existingScores
}
}
Constants.FirebaseCollection.gamesCollection.document(documentId).updateData(data) { error in
if let error = error {
print(error.localizedDescription)
}
print("Game updated")
}
}

Save the multiply array Swift

I am tried to add more than one array but it delete old and create new one. How can I add more / insert another array to UserDefaults? Here my code:
let foodArray = ["Title": String(fShop_TitleInput.text ?? ""), "QTY": String(fShop_QTYInput.text ?? ""), "Price": String(fShop_PriceInput.text ?? "")]
fShop_UserDefault.set(foodArray, forKey: "FoodArraySave")
let getFoodArray = fShop_UserDefault.object(forKey: "FoodArraySave")
print(getFoodArray ?? "No Array")
This work fine, but will save only one array at time. Example, I create new array title will be TestOne. If I add new title will be TestTwo, the array erase TestOne. How can I solve it?
As matt points out, your data is of type Dictionary, aka [String: Any]. Whenever you save it to UserDefaults, it gets overwritten, because you're writing to the same key. If you want to add more data to the same key, you'll have to convert your dictionary to an array of dictionaries: [[String: Any]]. Then you can access individual dictionaries by enumeration, or by accessing the particular index you're interested in.
The other way would be to save each piece of data in a different key, like "FoodArraySave1", "FoodArraySave2", "FoodArraySave3". That's probably more involved and less efficient though.
This is probably what you want to do:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var myFoodData: [[String: Any]] = []
let foodArray: [String: Any] = ["Title": "Eggs", "QTY": 18, "Price": 5.50]
let foodArray2: [String: Any] = ["Title": "Bacon", "QTY": 12, "Price": 12.50]
myFoodData.append(foodArray)
UserDefaults.standard.set(myFoodData, forKey: "FoodArraySave")
var getFoodData = UserDefaults.standard.object(forKey: "FoodArraySave") as! [[String: Any]]
print(getFoodData[0])
myFoodData.append((foodArray2))
UserDefaults.standard.set(myFoodData, forKey: "FoodArraySave")
getFoodData = UserDefaults.standard.object(forKey: "FoodArraySave") as! [[String: Any]]
print(getFoodData[1])
}

Swift UserDefaults get values from array

I have UserDefaults array like:
let userValue = ["name": self.nameLbl.text ?? "", "lastName": self.lastNameLbl.text ?? "", "city": cityLbl.text ?? ""] as! [String : String]
var userArray = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
userArray.append(userValue)
UserDefaults.standard.set(userArray, forKey: "userInfo")
How can I get key values example to print type
[["name": .., "lastName":..,],["name": .., "lastName":..,],["name": .., "lastName":..,]...]
If I print like this :
if let array = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] {
for dictionary in array {
print(dictionary["name"])
print(dictionary["lastName"])
print(dictionary["city"])
}
}
in console get :
Lars
James
Ulrich
Hetfield
Gentofte
California
I want it like this : [[ Lars, Ulrich,Gentofte],[James, Hetfield, California]]
You have to add key-value pair in the array and then print array. You will get your expected answer
let userValue = ["name": self.nameLbl.text ?? "", "lastName": self.lastNameLbl.text ?? "", "city": cityLbl.text ?? ""] as! [String : String]
var userArray = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
// Appending the different -2 userValue to userArray
userArray.append(userValue)
userArray.append(userValue)
UserDefaults.standard.set(userArray, forKey: "userInfo")
if let array = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] {
var dataValues = Array<Any>()
array.forEach { (object) in
dataValues.append(Array(object.values))
}
print(dataValues)
}
Here you can check demo:
let userValue = ["name": "j", "lastName": "o", "city": "g"] as! [String : String]
// Appending the different -2 userValue to userArray
var a = [userValue, userValue, userValue]
var b = Array<Any>()
a.forEach { (object) in
b.append(Array(object.values))
}
print(b)
To add an key-value pair to existing array, you just to need to append userValue to your array. Like:
let userValue = ["name": self.nameLbl.text ?? "", "lastName": self.lastNameLbl.text ?? "", "city": cityLbl.text ?? ""] as! [String : String]
var userArray = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
// Append the userValue to userArray
userArray.append(userValue)
UserDefaults.standard.set(userArray, forKey: "userInfo")
To fetch the dictionary from the array you can use
if let array = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] {
for dictionary in array {
print(dictionary["name"])
print(dictionary["lastName"])
print(dictionary["city"])
}
}

NSUserDefaults check if value exist for key

I have UICollectionView contains: UIlabel and UIButton (text in labels comes from API)
when I press UIButton text from UIlabel and CostLbl stored in UserDefaults.standard.array(forKey: "car")
let imageData = UIImageJPEGRepresentation(image.image!, 1.0) as NSData?
let newValues = ["name": self.nameLbl.text ?? "", "price": self.costLbl.text ?? "", "image": imageData]
var mArray = UserDefaults.standard.array(forKey: "car") as? [[String: Any]]
maAr?.append(newValues)
Question : when UIButton is press need to check if text from UIlabel is in array(forKey: "car") , if not - can to stored for key,, and if text already in array(forKey: "car") cant add to array
I wrote as vadian suggested
var maAr = UserDefaults.standard.array(forKey: "car") as? [[String: Any]] ?? []
if !maAr.contains(where: newValues) {
maAr.append(newValues)
def.set(maAr, forKey: "car")
}
but catch error to (where: newValues) -
Cannot convert value of type '[String : Any]' to expected argument type '([String : Any]) throws -> Bool'
How can this be changed?
First of all declare the dictionary as [String:String] in this case there is no type cast and no annotation.
let newValues = ["name": nameLbl.text ?? "", "price": costLbl.text ?? ""]
Read the array, check if the array contains the value, if NO append the item and save the array back, if YES do nothing
var carArray = UserDefaults.standard.array(forKey: "car") as? [[String: String]] ?? []
if !carArray.contains(newValues) {
carArray.append(newValues)
UserDefaults.standard.set(carArray, forKey: "car")
}

Resave NSUserDefaults value for selected key for index.row

I have array NSUserDefaults type :
let userValue = ["name": self.nameLbl.text ?? "", "lastName": self.lastNameLbl.text ?? "", "city": cityLbl.text ?? ""] as! [String : String]
var userArray = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
UserDefaults.standard.set(userArray, forKey: "userInfo")
And save this array in first `ViewController`
In second ViewController Im display this array in UITAbleView
class ...
var userInfo = [[String:String]]()
override func viewDidLoad() {
super.viewDidLoad()
userInfo = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UserTableViewCell
var userItem = userInfo[indexPath.row]
cell.nameLbl?.text = item["name"]
cell.lastNameLbl.text = item["lastName"]
cell.cityLbl.text = item["city"]
and under UITAbleView I have 3 UIextField's and UIButton for the opportunity to change user information
When user pass text in UIextField's I want to resave value for key
How can I remove selected name and save new name to correctly user??
To Abhirajsinh Thakore answer :
Im update code in cellForRowAt
var userItem = userInfo[indexPath.row]
cell.nameLbl?.text = item["name"]
cell.lastNameLbl.text = item["lastName"]
cell.cityLbl.text = item["city"]
item["name"] = cell.nameLbl?.text
var maArray = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
item.updateValue(cell.nameLbl?.text, forKey: "name")
maArray.append(item)
But its not save
You can fetch your complete array from Userdefaults
Now do is that get the new values from textField and replace that at the specific indexPath.row
For e.g:
var userInfo = [[String:String]]()
let data = userInfo[indexPath.row]
data["name"] = txtName.text
data["address"] = txtAddress.text
And now store this full array back to userDefaults and you will get the updated Result every Time.
Hope this helps.
Edit with reference to the code
Do like this:
var maArray = UserDefaults.standard.array(forKey: "userInfo") as? [[String: String]] ?? []
let innerData = maArray[indexPath.row]
innerData["name"] = cell.nameLbl?.text
innerData["lastName"] = cell.lastNameLbl.text
innerData["city"] = cell.cityLbl.text
// And save the maArray back to userDefaults

Resources