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

前端 未结 1 1316
逝去的感伤
逝去的感伤 2021-01-17 12:59

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\')\

相关标签:
1条回答
  • 2021-01-17 13:15

    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)
    
    0 讨论(0)
提交回复
热议问题