如何将自定义对象的数组列表存储到NSUserDefaults?

class Item { var name: String var collectionId: Int init(name: String, collectionId: Int) { self.name = name self.collectionId = collectionId } } class ViewController:UIViewController { var itemList = [Item]() func recievedResults() { let defaults = NSUserDefaults.standardUserDefaults() defaults.setObject(self.itemList, forKey: "myList") } } 

我收到一个错误“属性列表不能包含'CFType'types的对象

如何存储和获取itemList到NSUserDefaults?

您需要为您的自定义类实现协议NSCoding。 请看这个Swift的例子 。

首先,你必须从编码器和解码器方法inheritanceNSObject的Item:

 class Item :NSObject { var name: String = "" var collectionId: Int = 0 init(name: String, collectionId: Int) { self.name = name self.collectionId = collectionId } init(coder decoder: NSCoder) { self.name = decoder.decodeObjectForKey("name") as String self.collectionId = decoder.decodeIntegerForKey("collectionId") } func encodeWithCoder(coder: NSCoder) { coder.encodeObject(self.name, forKey: "name") coder.encodeInt(Int32(self.collectionId), forKey: "collectionId") } } 

然后,这些函数是从NSUserDefaults插入和检索。

 func insertItems() { let defaults = NSUserDefaults.standardUserDefaults() let data = NSKeyedArchiver.archivedDataWithRootObject(itemList) NSUserDefaults.standardUserDefaults().setObject(data, forKey: "myList") } func retrieveItems() { let defaults = NSUserDefaults.standardUserDefaults() if let data = NSUserDefaults.standardUserDefaults().objectForKey("myList") as? NSData { let _mySavedList = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [Item] } } 

例:

 let item1 = Item(name: "Item 1", collectionId: 1) let item2 = Item(name: "Item 2", collectionId: 2) itemList.append(item1) itemList.append(item2) insertItems() retrieveItems() 

正如在这个堆栈溢出问题中所指出的,你不能在NSUserDefaults中存储自定义对象。

但是你可以使你的类NSCoding兼容,并存储来自NSKeyedArchiver.archivedDataWithRootObject(…)的NSData:

 class Item : NSObject, NSCoding { var name: String var collectionId: Int init(name: String, collectionId: Int) { self.name = name self.collectionId = collectionId } required init(coder aDecoder: NSCoder) { collectionId = aDecoder.decodeIntegerForKey("collectionId") name = aDecoder.decodeObjectForKey("name") as String } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(name, forKey: "name") aCoder.encodeInteger(collectionId, forKey: "collectionId") } } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() recievedResults() } var itemList = [Item]() func recievedResults() { self.itemList.append(Item(name: "test", collectionId: 2)) let defaults = NSUserDefaults.standardUserDefaults() defaults.setObject(NSKeyedArchiver.archivedDataWithRootObject(itemList), forKey: "myList") let data = defaults.objectForKey("myList") as NSData if let decodedList = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? [Item]{ print("first item: \(decodedList)") } } } 
 //This is for swift 3.1 xcode 8.3.3 class Book: NSObject, NSCoding { var title: String var author: String var pageCount: Int var categories: [String] var available: Bool // Memberwise initializer init(title: String, author: String, pageCount: Int, categories: [String], available: Bool) { self.title = title self.author = author self.pageCount = pageCount self.categories = categories self.available = available } // MARK: NSCoding required convenience init?(coder decoder: NSCoder) { guard let title = decoder.decodeObject(forKey: "title") as? String, let author = decoder.decodeObject(forKey: "author") as? String, let categories = decoder.decodeObject(forKey: "categories") as? [String] else { return nil } self.init( title: title, author: author, pageCount: decoder.decodeInteger(forKey: "pageCount"), categories: categories, available: decoder.decodeBool(forKey: "available") ) } func encode(with coder: NSCoder) { coder.encode(self.title, forKey: "title") coder.encode(self.author, forKey: "author") coder.encodeCInt(Int32(self.pageCount), forKey: "pageCount") coder.encode(self.categories, forKey: "categories") coder.encode(self.available, forKey: "available") } } //Set let data = NSKeyedArchiver.archivedDataWithRootObject(books) NSUserDefaults.standardUserDefaults().setObject(data, forKey: "books") //Get if let data = NSUserDefaults.standardUserDefaults().objectForKey("books") as? NSData { let books = NSKeyedUnarchiver.unarchiveObjectWithData(data) }