#ios15 #nskeyedunarchiver #xcode13
Вопрос:
Я использую систему хранения файлов для сохранения некоторых моделей данных в соответствии с кодируемым протоколом.
Моя функция сохранения выглядит следующим образом:
func save<T: Encodable>(value: T, for key: String, on path: URL) throws {
let url = path.appendingPathComponent(key, isDirectory: false)
do {
try ANFileManager.createDirectoryAtPath(path: url.deletingLastPathComponent())
let archiver = NSKeyedArchiver(requiringSecureCoding: true)
archiver.outputFormat = .binary
try archiver.encodeEncodable(value, forKey: NSKeyedArchiveRootObjectKey)
archiver.finishEncoding()
// then you can use encoded data
try archiver.encodedData.write(to: url)
} catch {
throw StorageError.cantWrite(error)
}
}
Моя функция выборки выглядит следующим образом:
func fetchValue<T: Decodable>(for key: String, from path: URL) throws -> T {
let url = path.appendingPathComponent(key)
let data = try Data(contentsOf: url)
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
unarchiver.decodingFailurePolicy = .setErrorAndReturn
guard let decoded = unarchiver.decodeDecodable(T.self, forKey:
NSKeyedArchiveRootObjectKey) else {
throw StorageError.notFound
}
unarchiver.finishDecoding()
if let error = unarchiver.error {
throw StorageError.cantRead(error)
}
else {
return decoded
}
}
Сохранение и извлечение работают нормально, но во время выполнения я вижу предупреждение ниже в консоли xcode.
*** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSString' (0x7fff863014d0) [/Applications/Xcode_13.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework]' for key 'NS.keys', even though it was not explicitly included in the client allowed classes set: '{(
"'NSDictionary' (0x7fff862db9a0) [/Applications/Xcode_13.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework]",
"'NSDate' (0x7fff862db798) [/Applications/Xcode_13.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework]"
)}'. This will be disallowed in the future.
Что следует сделать, чтобы подавить предупреждение ?
Комментарии:
1. Можно спросить, почему вы тратите так много усилий, проходя через NSKeyedUnarchiver, когда кодируемый файл можно так просто сохранить непосредственно в виде списка свойств или json?
2. Хотите сохранить файл, который сначала является нечитаемым текстом.
3. Кроме того, мои модели были перенесены из NSCoding в Codable.
4. Мне жаль, но это смешно. Кодировка для архиватора с ключом и для списка кодируемых свойств идентична. В том, что вы делаете, нет ничего менее «читабельного». И они поддаются кодированию сейчас, так зачем же жить прошлым?
5. Хорошо, я понимаю это. Я использовал KeyArchiver для своих моделей, подтверждающих NSCoding. И продолжайте использовать ту же функцию хранения после преобразования моделей в Кодируемые. Я думаю, что мне следует изменить это сейчас.
Ответ №1:
Проблема заключается в том, что не требуется безопасное кодирование на разархиваторе:
https://developer.apple.com/documentation/foundation/nskeyedunarchiver/1410824-requiressecurecoding
Но в более широком смысле очень странно проходить через архив с ключом, когда кодируемый уже является жестоко прямым.
Комментарии:
1. unarchiver.requiresSecureCoding = false, Добавил это, но все равно вижу то же предупреждение.
2. Потому что это должно быть правдой!
3. Я попытался удалить весь код, связанный с архиватором с ключом, но, тем не менее, приложение видело это предупреждение. Я думаю, что это проблема с библиотекой firebase, потому что удаление инициализации Firebase, похоже, удаляет предупреждение.