2014-10-03 4 views
11

Muszę nieprawidłowo używać niestandardowych obiektów dla NSUserDefaults. Błąd "Lista właściwości jest nieprawidłowa dla formatu: 200 (listy właściwości nie mogą zawierać obiektów typu" CFType ")". Poniżej znajduje się mój kod, klasa celu jest szczególnie interesująca, ponieważ właśnie tu zaadaptowałem protokół NSCoding.NSUserDefaults Obiekt niestandardowy - Lista właściwości jest nieprawidłowa dla formatu: 200 (listy właściwości nie mogą zawierać obiektów typu CFType)

Ten kod jest globalny.

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

Ten kod znajduje się w 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) 
     } 
    } 

Ten kod należy do klasy Goal.

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 
    } 

} 
+0

Przypuszczam, że jeden z 'title' Państwa obiekt celem jest zerowa . Czy jest to linia: 'goalsArray [index] .title = cell.goalTextField.text' gwarantował ustawienie jej na niezerową wartość? –

+0

tak, jest gwarantowana liczba zerowa – CaptainCOOLGUY

Odpowiedz

5

Mam zamiar po prostu skopiować kod z projektem roboczym mam:

tutaj jest gra klasa obiektu z danymi z gry matematyczne kart flash:

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

Ta część wyglądem mniej więcej tak samo jak twoje, ale z bardziej zmiennymi typami. Klasy Archiver retriever i różnią się od siebie:

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

Wreszcie kod do przechowywania i pobierania z poziomu 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) 
+0

Steve, myślę, że byłoby dobrze dodać protokół NSCoding do deklaracji twojej klasy GameData –

Powiązane problemy