【问题标题】:How to solve deprecation of unarchiveObject(withFile:)如何解决 unarchiveObject(withFile:) 的弃用问题
【发布时间】:2019-04-05 10:33:59
【问题描述】:

在 iOS 12.1 中,unarchiveObject(withFile:) 已被弃用。
如何将NSKeyedUnarchiver.unarchiveObject(withFile: String) 转换为使用对NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data: Data)NSKeyedUnarchiver.unarchivedObject(ofClasses: [AnyClass] 的调用,来自:Data) 或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()
    }
}

【问题讨论】:

  • 这不是一个答案:但Data You Can Trust WWDC 2018 session 谈论新的 API 以及它们与旧的和现已弃用的 API 的区别。
  • 您问题中的代码是对单个键进行编码或解码。您能否也显示您当前调用unarchiveObject(withFile:) 的代码?
  • @DavidRönnqvist 我已更新帖子以包含调用 unarchiveObject(withFile:) 的代码。我也会看看你提供的链接。感谢您的帮助。

标签: ios swift nskeyedarchiver


【解决方案1】:

我不知道这是否是最好的解决方案,但这为我解决了转换问题(旧代码注释掉以供比较):

    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()
        }
 */
}

【讨论】:

    【解决方案2】:

    问题:取消归档 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)
    

    【讨论】:

    • unarchiveTopLevelObjectWithData 现在也已弃用。使用unarchivedObjectOfClass
    【解决方案3】:

    Swift 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
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      作为suggested by Apple,我们应该使用FileManager来读取/写入归档文件。

      func archiveURL() -> URL? {
          guard let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first 
              else { return nil }
      
          return documentURL.appendingPathComponent("MyArchive.data")
      }
      
      func archive(customObject: CustomObject) {
          guard let dataToBeArchived = try? NSKeyedArchiver.archivedData(withRootObject: customObject, requiringSecureCoding: true), 
              let archiveURL = archiveURL() 
              else  {
              return
          }
      
          try? dataToBeArchived.write(to: archiveURL)
      }
      
      func unarchive() -> CustomObject? {
          guard let archiveURL = archiveURL(),
              let archivedData = try? Data(contentsOf: archiveURL),
              let customObject = (try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedData)) as? CustomObject 
              else {
              return nil
          }
      
          return customObject
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-10
        • 2018-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-18
        • 1970-01-01
        相关资源
        最近更新 更多