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