💊
NSKeyedUnarchiver.unarchivedObjectで[Int]などの配列を解凍するときのエラー対策
Xcode 14.2
iOS 16.3.1
[Int]
を含むデータを
func archivedData(withRootObject object: Any, requiringSecureCoding requiresSecureCoding: Bool) throws -> Data
でアーカイブしたものを、アンアーカイブで取り出す時、
static func unarchivedObject(ofClasses classes: [AnyClass], from data: Data) throws -> Any?
を使うが、このとき classes
の指定に NSArray.self
, NSNumber.self
を含むことが必要となる。ここは解凍時に解釈に使用するクラスを指定するものである。
モデル
class A: NSObject, NSSecureCoding {
var b: [Int] = [1, 2, 3]
override init() {
super.init()
}
required init(coder aDecoder: NSCoder) {
b = aDecoder.decodeObject(forKey: "b") as? [Int] ?? []
super.init()
}
func encode(with aCoder: NSCoder) {
aCoder.encode(b, forKey: "b")
}
static var supportsSecureCoding: Bool {
true
}
}
処理部(対策後)
例によってファイルに書き込んですぐに取り出す。
let a = A() //モデルデータ
let fileURL = ファイルのURL
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: a, requiringSecureCoding: true)
try data.write(to: fileURL)
} catch let e {
print(e)
}
if let data = try? Data(contentsOf: fileURL) {
do {
let unarchived = try NSKeyedUnarchiver.unarchivedObject(
ofClasses: [A.self, NSArray.self, NSNumber.self],
from: data) as? A
} catch let e {
print(e)
}
}
エラー文
NSArray.self
, NSNumber.self
を指定しなかった時のエラー文を記事の検索のために載せる。
Error Domain=NSCocoaErrorDomain Code=xxxx "value for key 'b' was of unexpected class 'NSArray' (アドレス) [/System/Library/Frameworks/CoreFoundation.framework].
Allowed classes are:
{(
"'TEST_StoreData.A' (アドレス) [/private/var/containers/Bundle/Application/アプリの番号/TEST_StoreData.app]"
)}"
bのキーで取り出した値はNSArrayという想定しないものである
想定しているのは以下である。
'TEST_StoreData.A'
と言っている。よって、想定に NSArray.self
を加える。 NSNumber.self
も同様のエラーが出るので同様に加える。加えた結果が上の「処理部(対策後)」である。
Discussion