Предупреждение Xcode 13 — [NSKeyedUnarchiver проверяет класс:forKey:]

#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, похоже, удаляет предупреждение.