如何将 [[Bool]] 保存在 Swift 中(对布尔数组的存档数组进行编码)
How to save [[Bool]] in Swift (Encode for archive array of Boolean arrays)
我在归档 Int、String、Bool 和 Date 时没有困难,但归档布尔数组的数组时不起作用,这是代码的一部分:
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]]。有没有更好的编码方式?
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]]
但是还是不行?
还有其他想法吗?
这个简单的示例几乎是 [[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]])
这意味着在取消存档后,您可以一次性取回您的值。
我在归档 Int、String、Bool 和 Date 时没有困难,但归档布尔数组的数组时不起作用,这是代码的一部分:
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]]。有没有更好的编码方式?
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]]
但是还是不行?
还有其他想法吗?
这个简单的示例几乎是 [[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]])
这意味着在取消存档后,您可以一次性取回您的值。