NSUserDefaults Custom object - Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I must be incorrectly using Custom Objects for NSUserDefaults. The error " Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')". Below is my code, the Goal class is of particular interest, since this is where I am adopting the NSCoding protocol.

This code is global.

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

This code is in 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)         }     } 

This code is in the Goal class.

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

回答1:

I am going to just copy code from a working project I have:

here is the Game object class with data from a math flash card game:

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

This part looks about the same as yours, but with more variable types. The archiver and retriever classes differ from you:

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

Finally, the code for storing and retrieving from within a 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) 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!