Swift 4.2にアップグレードしてから、NSKeyedUnarchiverおよびNSKeyedArchiverメソッドの多くが廃止され、データをアーカイブ解除するためにtypeメソッドstatic func unarchivedObject<DecodedObjectType>(ofClass: DecodedObjectType.Type, from: Data) -> DecodedObjectType?
を使用する必要があることがわかりました。
NSObjectサブクラスである、オーダーメイドクラスWidgetDataの配列を正常にアーカイブできました。
private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> NSData {
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: widgetDataArray as Array, requiringSecureCoding: false) as NSData
else { fatalError("Can't encode data") }
return data
}
このデータは、このデータをアーカイブ解除しようとすると発生します。
static func loadWidgetDataArray() -> [WidgetData]? {
if isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA) {
if let unarchivedObject = UserDefaults.standard.object(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) as? Data {
//THIS FUNCTION HAS NOW BEEN DEPRECATED:
//return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [WidgetData]
guard let nsArray = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: unarchivedObject as Data) else {
fatalError("loadWidgetDataArray - Can't encode data")
}
guard let array = nsArray as? Array<WidgetData> else {
fatalError("loadWidgetDataArray - Can't get Array")
}
return array
}
}
return nil
}
ただし、Array.self
の代わりにNSArray.self
を使用することは許可されていないため、これは失敗します。何が間違っているのですか?これを修正してアレイをアーカイブ解除するにはどうすればよいですか?
unarchiveTopLevelObjectWithData(_:)
を使用して、archivedData(withRootObject:requiringSecureCoding:)
によってアーカイブされたデータをアーカイブ解除できます。 (これはまだ非推奨ではないと思います。)
ただし、コードを表示する前に、次のことを改善する必要があります。
NSData
の使用を避け、代わりにData
を使用してください
使用を避ける try?
デバッグに役立つエラー情報を破棄します
不要なキャストをすべて削除する
これを試して:
private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> Data {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: widgetDataArray, requiringSecureCoding: false)
return data
} catch {
fatalError("Can't encode data: \(error)")
}
}
static func loadWidgetDataArray() -> [WidgetData]? {
guard
isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA), //<- Do you really need this line?
let unarchivedObject = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA)
else {
return nil
}
do {
guard let array = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(unarchivedObject) as? [WidgetData] else {
fatalError("loadWidgetDataArray - Can't get Array")
}
return array
} catch {
fatalError("loadWidgetDataArray - Can't encode data: \(error)")
}
}
ただし、新しいアプリを作成する場合は、Codable
の使用を検討する必要があります。
_unarchiveTopLevelObjectWithData(_:)
_
廃止されました。したがって、安全なコーディングなしでデータをアーカイブ解除するには、次のことが必要です。
init(forReadingFrom: Data)
でNSKeyedUnarchiver
を作成しますrequiresSecureCoding
をfalseに設定します。decodeObject(of: [AnyClass]?, forKey: String) -> Any?
を呼び出してオブジェクトを取得し、適切なクラスとNSKeyedArchiveRootObjectKey
asキーを使用するだけです。 if #available(iOS 12.0, *) {
guard let unarchivedFavorites = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(favoritesData!)
else {
return
}
self.channelFavorites = unarchivedFavorites as! [ChannelFavorite]
} else {
if let unarchivedFavorites = NSKeyedUnarchiver.unarchiveObject(with: favoritesData!) as? [ChannelFavorite] {
self.channelFavorites = unarchivedFavorites
}
//データの達成
if #available(iOS 12.0, *) {
// use iOS 12-only feature
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: channelFavorites, requiringSecureCoding: false)
UserDefaults.standard.set(data, forKey: "channelFavorites")
} catch {
return
}
} else {
// handle older versions
let data = NSKeyedArchiver.archivedData(withRootObject: channelFavorites)
UserDefaults.standard.set(data, forKey: "channelFavorites")
}
これは私が私のコードを更新し、私のために働いている方法です
あなたはおそらくこれを探しています:
if let widgetsData = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) {
if let widgets = (try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, WidgetData.self], from: widgetsData)) as? [WidgetData] {
// your code
}
}