Reputation: 6253
I need create an array to add objects with this format like a dictionary in Swift : ["key1": "value1", "key2": "value2"]
When I try to save it with NSUserDefaults
all is correct, but when read NSUserDefaults
with the key this crashes. What type of data does my var obj need?
let def = NSUserDefaults.standardUserDefaults()
var key = "keySave"
var element: AnyObject!
var array1: [AnyObject!] = []
array1.append(["key1": "val1", "key2": "val2"])
array1.append(["key1": "val1", "key2": "val2"])
//save
var savestring : [AnyObject!]
savestring = array1
var defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(savestring, forKey: key)
defaults.synchronize()
//read
var obj: [AnyObject!] = []
if(obj != nil){
print("size: ")
print(obj.count) //vary long value confused..
element = obj[0] //crash
print(element.objectForKey("key1"))
}
Upvotes: 98
Views: 126340
Reputation: 51
Here is:
var array : [String] = ["One", "Two", "Three"]
let userDefault = UserDefaults.standard
// set
userDefault.set(array, forKey: "array")
// retrieve
if let fetchArray = userDefault.array(forKey: "array") as? [String] {
// code
}
Upvotes: 5
Reputation: 1019
If you are working with Swift 5+ you have to use UserDefaults.standard.setValue(value, forKey: key)
and to get saved data you have to use UserDefaults.standard.dictionary(forKey: key)
.
Upvotes: 0
Reputation: 511556
The question reads "array of array" but I think most people probably come here just wanting to know how to save an array to UserDefaults
. For those people I will add a few common examples.
Save array
let array = ["horse", "cow", "camel", "sheep", "goat"]
let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedStringArray")
Retrieve array
let defaults = UserDefaults.standard
let myarray = defaults.stringArray(forKey: "SavedStringArray") ?? [String]()
Save array
let array = [15, 33, 36, 723, 77, 4]
let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedIntArray")
Retrieve array
let defaults = UserDefaults.standard
let array = defaults.array(forKey: "SavedIntArray") as? [Int] ?? [Int]()
Save array
let array = [true, true, false, true, false]
let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedBoolArray")
Retrieve array
let defaults = UserDefaults.standard
let array = defaults.array(forKey: "SavedBoolArray") as? [Bool] ?? [Bool]()
Save array
let array = [Date(), Date(), Date(), Date()]
let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedDateArray")
Retrieve array
let defaults = UserDefaults.standard
let array = defaults.array(forKey: "SavedDateArray") as? [Date] ?? [Date]()
Custom objects (and consequently arrays of objects) take a little more work to save to UserDefaults
. See the following links for how to do it.
??
) allows you to return the saved array or an empty array without crashing. It means that if the object returns nil, then the value following the ??
operator will be used instead.Int
, Bool
, and Date
. I also tested it with Double
. As far as I know, anything that you can save in a property list will work like this. Upvotes: 262
Reputation: 8281
Just to add on to what @Zaph says in the comments.
I have the same problem as you, as to know, the array of String
is not saved. Even though Apple bridges types such as String and NSString, I wasn't able to save an array of [String]
neither of [AnyObject]
.
However an array of [NSString]
works for me.
So your code could look like that :
var key = "keySave"
var array1: [NSString] = [NSString]()
array1.append("value 1")
array1.append("value 2")
//save
var defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(array1, forKey: key)
defaults.synchronize()
//read
if let testArray : AnyObject? = defaults.objectForKey(key) {
var readArray : [NSString] = testArray! as [NSString]
}
Note that I created an array of NSString and not a dictionary. I didn't check if it works with a dictionary, but probably you will have to define the things as [NSString : NSString]
to have it working.
EDIT
Re-reading your question and your title, you are talking of array of array
. I think that as long as you stay with NSString
, an array of array will work. However, if you think my answer is irrelevant, just let me know in the comments and I will remove it.
Upvotes: 16
Reputation: 13234
Swift 4.0
Store:
let arrayFruit = ["Apple","Banana","Orange","Grapes","Watermelon"]
//store in user default
UserDefaults.standard.set(arrayFruit, forKey: "arrayFruit")
Fetch:
if let arr = UserDefaults.standard.array(forKey: "arrayFruit") as? [String]{
print(arr)
}
Upvotes: 6
Reputation: 24884
Here is an example of reading and writing a list of objects of type SNStock
that implements NSCoding
- we have an accessor for the entire list, watchlist
, and two methods to add and remove objects, that is addStock(stock: SNStock)
and removeStock(stock: SNStock)
.
import Foundation
class DWWatchlistController {
private let kNSUserDefaultsWatchlistKey: String = "dw_watchlist_key"
private let userDefaults: NSUserDefaults
private(set) var watchlist:[SNStock] {
get {
if let watchlistData : AnyObject = userDefaults.objectForKey(kNSUserDefaultsWatchlistKey) {
if let watchlist : AnyObject = NSKeyedUnarchiver.unarchiveObjectWithData(watchlistData as! NSData) {
return watchlist as! [SNStock]
}
}
return []
}
set(watchlist) {
let watchlistData = NSKeyedArchiver.archivedDataWithRootObject(watchlist)
userDefaults.setObject(watchlistData, forKey: kNSUserDefaultsWatchlistKey)
userDefaults.synchronize()
}
}
init() {
userDefaults = NSUserDefaults.standardUserDefaults()
}
func addStock(stock: SNStock) {
var watchlist = self.watchlist
watchlist.append(stock)
self.watchlist = watchlist
}
func removeStock(stock: SNStock) {
var watchlist = self.watchlist
if let index = find(watchlist, stock) {
watchlist.removeAtIndex(index)
self.watchlist = watchlist
}
}
}
Remember that your object needs to implement NSCoding
or else the encoding won't work. Here is what SNStock
looks like:
import Foundation
class SNStock: NSObject, NSCoding
{
let ticker: NSString
let name: NSString
init(ticker: NSString, name: NSString)
{
self.ticker = ticker
self.name = name
}
//MARK: NSCoding
required init(coder aDecoder: NSCoder) {
self.ticker = aDecoder.decodeObjectForKey("ticker") as! NSString
self.name = aDecoder.decodeObjectForKey("name") as! NSString
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(ticker, forKey: "ticker")
aCoder.encodeObject(name, forKey: "name")
}
//MARK: NSObjectProtocol
override func isEqual(object: AnyObject?) -> Bool {
if let object = object as? SNStock {
return self.ticker == object.ticker &&
self.name == object.name
} else {
return false
}
}
override var hash: Int {
return ticker.hashValue
}
}
Hope this helps!
Upvotes: 11
Reputation: 822
Try this.
To get the data from the UserDefaults.
var defaults = NSUserDefaults.standardUserDefaults()
var dict : NSDictionary = ["key":"value"]
var array1: NSArray = dict.allValues // Create a dictionary and assign that to this array
defaults.setObject(array1, forkey : "MyKey")
var myarray : NSArray = defaults.objectForKey("MyKey") as NSArray
println(myarray)
Upvotes: 3