【问题标题】:How to save [[Bool]] in Swift (Encode for archive array of Boolean arrays)如何在 Swift 中保存 [[Bool]](布尔数组存档数组的编码)
【发布时间】:2017-03-03 18:05:13
【问题描述】:

我在归档 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]]

但这仍然不起作用?

还有其他想法吗?

【问题讨论】:

  • 无法怎么办?相反会发生什么?错误信息等?
  • 我把这段代码放在操场上,并且能够重现同样的奇怪行为。目前我无法完全调查该问题,但我的建议是先尝试将对象转换为 NSData,然后保存数据,然后使用 NSKeyedUnarchiver.unarchiveObjectWithData(data) 检索数据
  • 没有错误,只是没有数据。
  • werm098:我尝试了您的建议,但它不起作用,请参阅上面的代码。关于如何保存 [[Bool]] 的任何其他想法

标签: ios arrays swift archive nscoding


【解决方案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]])

这意味着在取消归档后,您可以一次性恢复您的值。

【讨论】:

  • 它工作正常,只是在重新启动应用程序时无法正确读取。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
  • 2011-03-10
  • 1970-01-01
相关资源
最近更新 更多