Как обновить NSKeyedUnarchiver unarchiveObjectWithData до NSKeyedUnarchiver unarchivedObjectOfClass: [fromData: error: - PullRequest
1 голос
/ 21 сентября 2019

Мое приложение в настоящее время использует эту устаревшую функцию:

id unarchivedObject=[NSKeyedUnarchiver unarchiveObjectWithData:codedData];
if([unarchivedObject isKindOfClass:[NSDictionary class]]){
    // currently returns TRUE when reading existing user data.
} 

Для обновления я преобразовал ее в:

id unarchivedObject=[NSKeyedUnarchiver unarchivedObjectOfClass:[NSDictionary class] fromData:codedData error:nil];
if([unarchivedObject isKindOfClass:[NSDictionary class]]){
    // currently returns FALSE when reading existing user data.
}

Данные изначально были закодированы следующим образом:

-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:text forKey:@"text"];
}
-(instancetype)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        text=[decoder decodeObjectForKey:@"text"];
}

Что может быть причиной того, что оператор IF возвращает FALSE, используя более новый код?

Обратите внимание, что меня интересует, прежде всего, чтение существующих данных, хранящихся до устаревания функций архивирования.Простое переключение на более новые функции не решает проблему.

1 Ответ

0 голосов
/ 21 сентября 2019

Интересный вопрос!Я поддерживаю iOS 10.0, поэтому я не сталкивался с такой проблемой, пока не увидел это.Я возился в течение часа и успешно обнаружил проблему.

Что может быть причиной того, что оператор IF возвращает FALSE, используя более новый код?

Это потому, что вы unarchivedObject object is nil !

Если вы используете параметр error в новом методе, вы увидите ошибку, подобную этой:

Error Domain= NSCocoaErrorDomain Code = 4864 "Этот декодер будет декодировать только те классы, которые принимают NSSecureCoding. Класс 'QTPerson' не принимает его."UserInfo = {NSDebugDescription = Этот декодер будет декодировать только те классы, которые принимают NSSecureCoding.Класс 'QTPerson' не принимает его.

Но как нам получить правильное значение для этого unarchivedObject, а не ноль?Это займет пару шагов.

Прежде всего, приведите вашу модель / класс в соответствие <NSCoding, NSSecureCoding>

Пример: QTPerson.h

#import <Foundation/Foundation.h>

@class QTPerson;

NS_ASSUME_NONNULL_BEGIN

#pragma mark - Object interfaces

@interface QTPerson : NSObject <NSCoding, NSSecureCoding>
@property (nonatomic, copy) NSString *text;
@end

NS_ASSUME_NONNULL_END

А затем реализовать методы протокола:

QTPerson.m

#import "QTPerson.h"

@implementation QTPerson

+ (BOOL)supportsSecureCoding {
    return YES;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:_text forKey:@"text"];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _text = [coder decodeObjectOfClass:[NSString class] forKey:@"text"];
    }
    return self;
}

@end

А затем при архивации объекта вы захотите передать YES до параметра requiringSecureCoding, вот так:

QTPerson *person = [[QTPerson alloc] init];
person.text = @"Glenn";

NSData *codedData1 = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setValue:codedData1 forKey:@"boom"];

Наконец, при разархивировании, просто делайте то, что вы сделали правильно, вот так:

NSData *codedData = [[NSUserDefaults standardUserDefaults] dataForKey:@"boom"];

NSError *er;
id unarchivedObject=[NSKeyedUnarchiver unarchivedObjectOfClass:[QTPerson class] fromData:codedData error:&er];

if([unarchivedObject isKindOfClass:[QTPerson class]]){
    NSLog(@"TRUE!");
} else {
    NSLog(@"FALSE!");
}

Вуаля!Вы получите ненулевой объект unarchivedObject, следовательно, значение ИСТИНА / ДА, которое вы ищете!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...