2016-10-21 3 views
0

У меня нетрудно архивировать Int, String, Bool и Date, но архивирование массива булевых массивов не работает, вот часть кода:Как сохранить [[Bool]] в Swift (Encode for archive array из булевых массивов)

class PlayerInfo: NSObject, NSCoding 
{ 
    public var score: Int = 0 
    public var lastPlayed: Date = Date() 
    public var visited: [[Bool]] = [] 
    public var ringFound: Bool = false 

    init(dictionary: [String : AnyObject]) 
    { 
     score = dictionary[ArchiveKeys.Score] as! Int 
     lastPlayed = dictionary[ArchiveKeys.LastPlayed] as! Date 
     visited = dictionary[ArchiveKeys.Visited] as! [[Bool]]   
     ringFound = dictionary[ArchiveKeys.RingFound] as! Bool 
    } 

    func encode(with archiver: NSCoder) 
    { 
     archiver.encode(score, forKey: ArchiveKeys.Score) 
     archiver.encode(lastPlayed, forKey: ArchiveKeys.LastPlayed) 
     archiver.encode(visited, forKey: ArchiveKeys.Visited) 
     archiver.encode(ringFound, forKey: ArchiveKeys.RingFound) 
    } 

    required init(coder unarchiver: NSCoder) 
    { 
     super.init() 
     score = unarchiver.decodeInteger(forKey: ArchiveKeys.Score) 
     lastPlayed = unarchiver.decodeObject(forKey: ArchiveKeys.LastPlayed) as! Date 
     visited = unarchiver.decodeObject(forKey: ArchiveKeys.Visited) as! [[Bool]] 
     ringFound = unarchiver.decodeBool(forKey: ArchiveKeys.RingFound) 
    } 

    class func retrieveCurrentGame() -> PlayerInfo! 
    { 
     let filePath: String = retrievePreviousGameFilePath(fileName: currentGameName) 

     if let game = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? PlayerInfo 
     { 
      print("retrieving previous game - found a game for previous day") 
      return game 
     } 
     else 
     { 
      print("retrieving previous game - can't find game data") 
      return nil 
     } 
    } 

    class func retrievePreviousGameFilePath(fileName: String) -> String 
    { 
     let kFileNameExtension: String = ".game" 

     let fileNameWithExtension: String = fileName + kFileNameExtension 
     let fileManager = FileManager.default 
     let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL 
     print("url= " + (url.appendingPathComponent(fileNameWithExtension)?.path)!) 
     return (url.appendingPathComponent(fileNameWithExtension)?.path)! 

    } 

    public func saveCurrentGame() 
    { 
     let fileName: String = currentGameName + ".game" 
     let fileManager = FileManager.default 
     let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL 
     print("url= " + (url.appendingPathComponent(fileName)?.path)!) 
     let filePath: String = (url.appendingPathComponent(fileName)?.path)! 
     NSKeyedArchiver.archiveRootObject(self, toFile: filePath) 
    }  

} 

Я не могу получить [[Bool]], посетив мой код. Есть ли лучший способ кодирования?

Followup ДЛЯ werm098:

я пересмотрел кодировку:

 let visitedData: Data = NSKeyedArchiver.archivedData(withRootObject: visited) 
     archiver.encode(visitedData, forKey: ArchiveKeys.Visited) 
//  archiver.encode(visited, forKey: ArchiveKeys.Visited) 

и декодирование:

 let visitedData: Data = unarchiver.decodeObject(forKey: ArchiveKeys.Visited) as! Data 
     visited = NSKeyedUnarchiver.unarchiveObject(with: visitedData) as! [[Bool]] 
//  visited = unarchiver.decodeObject(forKey: ArchiveKeys.Visited) as! [[Bool]] 

Но это все еще не работает?

Любые другие идеи?

+0

Невозможно как? Что происходит вместо этого? Сообщение об ошибке и т. Д.? – Bill

+0

Я поставил этот код на детскую площадку и смог воспроизвести такое же странное поведение. В настоящее время я не могу полностью исследовать проблему, но мое предложение состоит в том, чтобы сначала попытаться преобразовать объект в NSData, а затем сохранить данные и затем получить данные с помощью 'NSKeyedUnarchiver.unarchiveObjectWithData (data)' – werm098

+0

Нет ошибки, просто нет данных. –

ответ

1

Этот простой пример в значительной степени является рабочим решением для [[Bool]], вы можете взглянуть на это и проверить, как это работает.

class MyClass: NSObject, NSCoding { 

    public var boolArray: [[Bool]]? = nil 

    // MARK: Init 

    override init() { 
     self.boolArray = [[true, false, false], [false, true, false], [true, true, false]] // or any random sequece... 
     debugPrint("It was inited.") 
    } 

    // MARK: - Archiving/Unarchiving 

    func archived() -> Data { 
     return NSKeyedArchiver.archivedData(withRootObject: self) 
    } 

    class func unarchived(fromData data: Data) -> MyClass? { 
     return NSKeyedUnarchiver.unarchiveObject(with: data) as? MyClass 
    } 

    // MARK: - <NSCoding> 

    private enum Key { 
     case boolArray 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(self.boolArray, forKey: String(describing: Key.boolArray)) 
     debugPrint("It was encoded.") 
    } 

    required init?(coder aDecoder: NSCoder) { 
     self.boolArray = aDecoder.decodeObject(forKey: String(describing: Key.boolArray)) as? [[Bool]] 
     debugPrint("It was decoded.") 
    } 

} 

и настало время, чтобы проверить:

let myClass = MyClass() 
debugPrint(myClass.boolArray) 

let archivedData: Data = myClass.archived() 
// do something with the data here... e.g. permanent storing 
// ... 

// ... 
// restore back the data here from e.g. background storage device 
let unarchivedObject: MyClass = MyClass.unarchived(fromData: archivedData) 

debugPrint(unarchivedObject.boolArray) 

и консоль должна выглядеть следующим образом:

"It was inited" 
Optional([[true, false, false], [false, true, false], [true, true, false]]) 
"It was encoded." 
"It was decoded." 
Optional([[true, false, false], [false, true, false], [true, true, false]]) 

, что означает, после того, как разархивировав вы можете получить обратно ваши ценности в одном куске.

+0

Он работал, просто не прочитав его правильно при перезагрузке приложения. Спасибо. –