Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to use method decodeObjectOfClass:forKey: to decode an object #302

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ihomway
Copy link

@ihomway ihomway commented Dec 4, 2018

Hello bireme,

Here is the reason why this pull request happened.

I have a model like this:

@interface HWPerson : NSObject <NSSecureCoding>

@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) NSURL *avatarURL;

@end

@implementation HWPerson

+ (BOOL)supportsSecureCoding {
    return YES;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [self yy_modelEncodeWithCoder:aCoder];
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    return [self yy_modelInitWithCoder:aDecoder];
}

@end

I'd like to use NSSecureCoding rather than NSCoding. Then something unexpected happened. I can NSKeyedArchiver to save this model to disk successfully, but I cannot read and unarchive it from the disk. There's an error.

After debug, I found it is because the NSURL property. This property cannot be unarchived in yy_modelInitWithCoder: with method decodeObjectforKey:. We have to use decodeObjectOfClass:forKey:.

Here is the example code to save and read this mode:

- (void)save {
    HWPerson *person = [[HWPerson alloc] init];
    person.firstName = @"will";
    person.lastName = @"chen";
    person.age = 28;
    person.avatarURL = [NSURL URLWithString:@"https://example.com/avatar.png"];

    if (@available(iOS 11, *)) {
        NSError *error = nil;
        NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:person
                                                   requiringSecureCoding:YES
                                                                   error:&error];
        if (!personData) {
            NSLog(@"Archiver Failed: %@", error.localizedDescription);
        }

        error = nil;
        BOOL result = [personData writeToFile:[self filePath]
                                      options:0
                                        error:&error];
        if (!result) {
            NSLog(@"Write to File Failed: %@", error.localizedDescription);
        }
    } else {
        BOOL result = [NSKeyedArchiver archiveRootObject:person toFile:[self filePath]];
        if (!result) {
            NSLog(@"Write to File Failed");
        }
    }
}

- (void)read {
    if (@available(iOS 11, *)) {
        NSError *error = nil;
        NSData *data = [NSData dataWithContentsOfFile:[self filePath]];
        HWPerson *person = [NSKeyedUnarchiver unarchivedObjectOfClass:HWPerson.class
                                                             fromData:data
                                                                error:&error];
        if (!person) {
            NSLog(@"Read from File Failed: %@", error.localizedDescription);
        } else {
            NSLog(@"%@·%@ is %ld", person.firstName, person.lastName, person.age);
            NSLog(@"Avatar URL: %@", person.avatarURL);
        }
    } else {
        HWPerson *person = [NSKeyedUnarchiver unarchiveObjectWithFile:[self filePath]];
        if (!person) {
            NSLog(@"Read from File Failed");
        } else {
            NSLog(@"%@·%@ is %ld", person.firstName, person.lastName, person.age);
            NSLog(@"Avatar URL: %@", person.avatarURL);
        }
    }
}

@codecov-io
Copy link

Codecov Report

Merging #302 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #302   +/-   ##
=======================================
  Coverage   99.28%   99.28%           
=======================================
  Files           2        2           
  Lines        1540     1540           
=======================================
  Hits         1529     1529           
  Misses         11       11
Impacted Files Coverage Δ
YYModel/NSObject+YYModel.m 99.21% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1230e60...351f45b. Read the comment docs.

@ihomway
Copy link
Author

ihomway commented Dec 5, 2018

In order to conform to NSSecureCoding:
An object that does not override initWithCoder: can conform to NSSecureCoding without any changes (assuming that it is a subclass of another class that conforms).
An object that does override initWithCoder: must decode any enclosed objects using the decodeObjectOfClass:forKey: method. For example:

id obj = [decoder decodeObjectOfClass:[MyClass class] forKey:@"myKey"];

In addition, the class must override the getter for its supportsSecureCoding property to return YES.

Link: NSSecureCoding

Andy0570 added a commit to Andy0570/YYKit that referenced this pull request Jul 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants