如何解决unarchiveObject(withFile :)的弃用

时间:2018-11-01 08:03:20

标签: ios swift nskeyedarchiver

在iOS 12.1中,不推荐使用unarchiveObject(withFile:)
您如何将NSKeyedUnarchiver.unarchiveObject(withFile: String)转换为使用对NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data: Data)NSKeyedUnarchiver.unarchivedObject(ofClasses: [AnyClass]的呼叫:数据)或NSKeyedUnarchiver.unarchivedObject(ofClass: NSCoding.Protocol, from: Data)

我猜您必须拥有类似let fileData = try Data(contentsOf: URL)的东西,然后使用这些方法之一来取消存档数据。但是,我无法弄清楚,而且折旧随附的文档没有帮助(至少对我而言)。

存档数据非常简单-只是一个字符串数组(此代码定义的NameToBeSaved类数组):

class NameToBeSaved: NSObject, NSCoding {
var name: String

init(userEnteredName: String) {
    self.name = userEnteredName
    super.init()
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "name")
}

required init?(coder aDecoder: NSCoder) {
    name = aDecoder.decodeObject(forKey: "name") as! String
    super.init()
}

这是调用unarchiveObject(withFile :)的代码-

init() {
    if let archivedCategoryNames = NSKeyedUnarchiver.unarchiveObject(withFile: categoryNameArchiveURL.path) as? [NameToBeSaved] {
        allCategories += archivedCategoryNames
    } else {
        for category in starterCategories {
            let thisNewCategory = NameToBeSaved(userEnteredName: category)
            createNewCategory(thisNewCategory)
        }
        sortCategories()
    }
}

4 个答案:

答案 0 :(得分:3)

我不知道这是否是最好的解决方案,但这对我来说解决了转换(旧代码已注释掉以便进行比较):

    init() {

    do {
        let rawdata = try Data(contentsOf: categoryNameArchiveURL)
        if let archivedCategoryNames = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(rawdata) as! [NameToBeSaved]? {
            allCategories += archivedCategoryNames
        }
    } catch {
        print("Couldn't read file")
        for category in starterCategories {
            let thisNewCategory = NameToBeSaved(userEnteredName: category)
            createNewCategory(thisNewCategory)
        }
        sortCategories()
    }

/*        if let archivedCategoryNames = NSKeyedUnarchiver.unarchiveObject(withFile: categoryNameArchiveURL.path) as? [NameToBeSaved] {
            allCategories += archivedCategoryNames
        } else {
            for category in starterCategories {
                let thisNewCategory = NameToBeSaved(userEnteredName: category)
                createNewCategory(thisNewCategory)
            }
            sortCategories()
        }
 */
}

答案 1 :(得分:3)

快捷键5 ,添加前缀“ NS”并集中使用以用于将来的更改...

class KeyedUnarchiver : NSKeyedUnarchiver {
    open override class func unarchiveObject(with data: Data) -> Any? {
        do {
            let object = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSObject.self], from: data)
            return object
        }
        catch let error {
            Swift.print("unarchiveObject(with:) \(error.localizedDescription)")
            return nil
        }
    }

    open override class func unarchiveObject(withFile path: String) -> Any? {
        do {
            let data = try Data(contentsOf: URL.init(fileURLWithPath: path))
            let object = try unarchivedObject(ofClasses: [NSObject.self], from: data)
            return object
        }
        catch let error {
            Swift.print("unarchiveObject(withFile:) \(error.localizedDescription)")
            return nil
        }
    }
}

答案 2 :(得分:2)

suggested by Apple一样,我们应该使用FileManager读取/写入存档文件。

guard let documentURL = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first else { return }

let filePath = "MyArchive.data"
let fileURL = documentURL.appendingPathComponent(filePath)

 // Archive
if let archivedData = try? NSKeyedArchiver.archivedData(withRootObject: myObject, requiringSecureCoding: true) {
    try? archivedData.write(to: fileURL)
}

// Unarchive
if let archivedData = try? Data(contentsOf: fileURL),
        let myObject = (try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedData)) as? Object {
    ///
    ///
    ///
}

答案 3 :(得分:0)

问题:取消存档一个sks文件以用作SKEmitterNode。

不建议使用的旧方法:

let filePath = Bundle.main.path(forResource: "myParticleEmitter", ofType: "sks")!
let burnerPathUnarchived = NSKeyedUnarchiver.unarchiveObject(withFile: burnerPath) as! SKEmitterNode

新方法:

do {
    let fileURL = Bundle.main.url(forResource: "myParticleEmitter", withExtension: "sks")!
    let fileData = try Data(contentsOf: fileURL)
    let unarchivedData = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(burnerData) as! SKEmitterNode
} catch {
    print("didn't work")
}

那么您可以做:

mySKEffectNode.addChild(unarchivedData)
mySKSpriteNode.addChild(mySKEffectNode)