NSUserDefaults自定义对象 – 属性列表无效,格式为:200(属性列表不能包含'CFType'types的对象)

我必须错误地使用自定义对象NSUserDefaults。 错误“属性列表格式无效:200(属性列表不能包含CFTypetypes的对象)”。 下面是我的代码,目标类特别感兴趣,因为这是我采用NSCoding协议。

这个代码是全球性的。

func saveGoals (goals : [Goal]) { var updatedGoals = NSKeyedArchiver.archivedDataWithRootObject(goals) NSUserDefaults.standardUserDefaults().setObject(updatedGoals, forKey: "Goals") NSUserDefaults.standardUserDefaults().synchronize() } func loadCustomObjectWithKey() -> [Goal] { if let encodedObject : NSData = NSUserDefaults.standardUserDefaults().objectForKey("Goals") as? NSData { var encodedObject : NSData? = NSUserDefaults.standardUserDefaults().objectForKey("Goals") as? NSData var goal : [Goal] = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as [Goal] return goal } else { return [Goal]() } } 

这段代码在GoalsViewController中。

 class GoalsViewController: MainPageContentViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet var tableView: GoalsTableView! var cell = GoalTableViewCell() var goalsArray : Array<Goal> = [] // override func viewDidLoad() { super.viewDidLoad() self.tableView.delegate = self self.tableView.dataSource = self if var storedGoals: [Goal] = loadCustomObjectWithKey() as [Goal]? { goalsArray = storedGoals } //retrieve data. var goal = Goal(title: "Walk the Dog") goalsArray.append(goal) saveGoals(goalsArray) self.tableView?.reloadData() tableView.estimatedRowHeight = 44.0 tableView.rowHeight = UITableViewAutomaticDimension var notification = NSNotificationCenter.defaultCenter() notification.addObserver(self, selector: "finishCreatingGoal:", name: "FinishCreatingGoal", object: nil) } func finishCreatingGoal(notification : NSNotification) { if (notification.name == "FinishCreatingGoal") { var userInfo = notification.userInfo! var text = userInfo["text"]! as String var index = userInfo["index"]! as Int var cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as GoalTableViewCell goalsArray[index].title = cell.goalTextField.text saveGoalList(goalsArray) self.tableView.reloadData() self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0), atScrollPosition: UITableViewScrollPosition.Middle, animated: true) } } 

此代码位于“目标”类中。

 import UIKit class Goal : NSObject, NSCoding { var title : String? = "" var checkmarked : Bool? = false var isLastCell : Bool? = false var enabled : Bool? = true var priority = Priority.defaultPriority override init() { } init(title : String) { self.title = title } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(title!, forKey: "title") aCoder.encodeBool(checkmarked!, forKey: "checkmarked") aCoder.encodeBool(isLastCell!, forKey: "isLastCell") aCoder.encodeBool(enabled!, forKey: "enabled") } required init(coder aDecoder: NSCoder) { title = aDecoder.decodeObjectForKey("title") as String! checkmarked = aDecoder.decodeBoolForKey("checkmarked") as Bool isLastCell = aDecoder.decodeBoolForKey("isLastCell") as Bool enabled = aDecoder.decodeBoolForKey("enabled") as Bool } } 

我要从一个正在运行的项目中复制代码:

这里是游戏对象类与math闪存卡游戏的数据:

 import Foundation class GameData: NSObject { var sign: String = "+" var level: Int = 1 var problems: Int = 10 var time: Int = 30 var skipWrong: Bool = true var usedTime: Int = 0 var correctCount: Int = 0 var correctTopNumber: [Int] = [Int]() var correctBottomNumber: [Int] = [Int]() var wrongTopNumber: [Int] = [Int]() var wrongBottomNumber: [Int] = [Int]() var date: NSDate = NSDate() func encodeWithCoder(aCoder: NSCoder!) { aCoder.encodeObject(sign, forKey: "sign") aCoder.encodeInteger(level, forKey: "level") aCoder.encodeInteger(problems, forKey: "problems") aCoder.encodeInteger(time, forKey: "time") aCoder.encodeBool(skipWrong, forKey: "skipWrong") aCoder.encodeInteger(usedTime, forKey: "usedTime") aCoder.encodeInteger(correctCount, forKey: "correctCount") aCoder.encodeObject(correctTopNumber, forKey: "correctTopNumber") aCoder.encodeObject(correctBottomNumber, forKey: "correctBottomNumber") aCoder.encodeObject(wrongTopNumber, forKey: "wrongTopNumber") aCoder.encodeObject(wrongBottomNumber, forKey: "wrongBottomNumber") aCoder.encodeObject(date, forKey: "date") } init(coder aDecoder: NSCoder!) { sign = aDecoder.decodeObjectForKey("sign") as String level = aDecoder.decodeIntegerForKey("level") problems = aDecoder.decodeIntegerForKey("problems") time = aDecoder.decodeIntegerForKey("time") skipWrong = aDecoder.decodeBoolForKey("skipWrong") usedTime = aDecoder.decodeIntegerForKey("usedTime") correctCount = aDecoder.decodeIntegerForKey("correctCount") correctTopNumber = aDecoder.decodeObjectForKey("correctTopNumber") as Array correctBottomNumber = aDecoder.decodeObjectForKey("correctBottomNumber") as Array wrongTopNumber = aDecoder.decodeObjectForKey("wrongTopNumber") as Array wrongBottomNumber = aDecoder.decodeObjectForKey("wrongBottomNumber") as Array date = aDecoder.decodeObjectForKey("date") as NSDate } override init() { } } 

这部分看起来和你一样,但是variablestypes更多。 归档器和检索器类与您不同:

 import Foundation class ArchiveGameData:NSObject { var documentDirectories:NSArray = [] var documentDirectory:String = "" var path:String = "" func ArchiveResults(#dataSet: [GameData]) { documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) documentDirectory = documentDirectories.objectAtIndex(0) as String path = documentDirectory.stringByAppendingPathComponent("results3.archive") if NSKeyedArchiver.archiveRootObject(dataSet, toFile: path) { //println("Success writing to file!") } else { println("Unable to write to file!") } } func RetrieveGameData() -> NSObject { var dataToRetrieve = [GameData]() documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) documentDirectory = documentDirectories.objectAtIndex(0) as String path = documentDirectory.stringByAppendingPathComponent("results3.archive") if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [GameData] { dataToRetrieve = dataToRetrieve2 } return(dataToRetrieve) } } 

最后,用于在ViewController中存储和检索的代码:

 //retrieveing var gameDataArray = ArchiveGameData().RetrieveGameData() as [GameData] //Archiving gameData = GameData() //create local object then append all the new data, then store it gameData.sign = buttonStates.sign gameData.level = buttonStates.level gameData.problems = buttonStates.problems gameData.time = buttonStates.time //etc. for all properties ArchiveGameData().ArchiveResults(dataSet: gameDataArray)