如何快速保存和读取 NSUserdefault 中的数组数组?

我需要创建一个数组来添加这种格式的对象,就像 Swift 中的字典一样: [“ key1”: “ value1”,“ key2”: “ value2”]

当我尝试用 NSUserDefaults保存它时,一切都是正确的,但是当用键读取 NSUserDefaults时,这个程序崩溃了。我的 var obj 需要什么类型的数据?

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"))
}
119421 次浏览

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)

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.

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!

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.

String array

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]()

Int array

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]()

Bool array

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]()

Date array

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]()

Object array

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.

Notes

  • The nil coalescing operator (??) 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.
  • As you can see, the basic setup was the same for 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.

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)
}

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
}

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).