如何解决 unarchiveObject(withFile:) 的弃用问题
Posted
技术标签:
【中文标题】如何解决 unarchiveObject(withFile:) 的弃用问题【英文标题】:How to solve deprecation of 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:) 的代码。我也会看看你提供的链接。感谢您的帮助。
【参考方案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
【讨论】:
以上是关于如何解决 unarchiveObject(withFile:) 的弃用问题的主要内容,如果未能解决你的问题,请参考以下文章
NSKeyedUnarchiver.unarchiveObject() 取消归档旧对象
NSKeyedUnarchiver.unarchiveObject 不工作 [重复]
NSKeyedArchiver.unarchiveObject Swift 3 iOS 10
如何解决“ValueError: Found array with dim 4. Estimator expected <= 2.”?
如何解决此错误 Command PhaseScriptExecution failed with a nonzero exit code