Mohammed Sadiq
Mohammed Sadiq

Reputation:

Converting a NSObject into NSData

I am having an issue in converting a NSObject into NSData. I have a class which inherits NSObject.

When i tried to convert the object of that particular class into NSData as follows :

NSData *dataOnObject = [NSKeyedArchiver archivedDataWithRootObject:classObject];

but it gives out exception stating that -[classObject encodeWithCoder:]: unrecognized selector sent to instance ..

I have also added the object to a newly created array as

NSMutableArray *wrapperedData = [NSMutableArray arrayWithObject: classObject];
NSData *dataOnObject = [NSKeyedArchiver archivedDataWithRootObject:value];

But still , its giving out exception.

So I need to extract the bytes from the object classObject.

Any help would be greatly appreciated ...

awaiting for your reply ...

Upvotes: 15

Views: 32020

Answers (6)

d1jhoni1b
d1jhoni1b

Reputation: 8025

This is a example of custom object converted to NSData (so it can be then saved into user defaults)

Create the following files:

Catalog.h

@interface Catalog : NSObject

@property (nonatomic, assign) int pk;
@property (nonatomic, copy) NSString *catalogName;
@property (nonatomic, copy) NSString *catalogDescription;
@property (nonatomic, assign) int catalogEdition;
@property (nonatomic, assign) int catalogTotalPages;

- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;

@end

Catalog.m

#import <Foundation/Foundation.h>
#import "Catalog.h"

@implementation Catalog

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.catalogName forKey:@"catalogName"];
    [aCoder encodeObject:self.catalogDescription forKey:@"catalogDescription"];
    [aCoder encodeInt:self.catalogEdition forKey:@"catalogEdition"];
    [aCoder encodeInt:self.catalogTotalPages forKey:@"catalogTotalPages"];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        self.catalogName = [aDecoder decodeObjectForKey:@"catalogName"];
        self.catalogDescription = [aDecoder decodeObjectForKey:@"catalogDescription"];
        self.catalogEdition = [aDecoder decodeIntForKey:@"catalogEdition"];
        self.catalogTotalPages = [aDecoder decodeIntForKey:@"catalogTotalPages"];
    }
    return self;
}

@end

Finally in your controller include header files

#import "Catalog.h"

And add this code to use your object (in this case im saving into user defaults)

            Catalog *catalog = [[Catalog alloc] init];
            catalog.catalogName = @"catalogName";
            catalog.catalogDescription = @"catalogName";
            catalog.catalogEdition = 1;

NOTE: in this line of code is where the actual data passing is taking place

//archiving object to nsdata
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:catalog];

[[NSUserDefaults standardUserDefaults] setObject:encodedObject forKey:@"keyName"];
[[NSUserDefaults standardUserDefaults] synchronize];

In case you want to get your object back from NSData

NSData *nsData = [[NSUserDefaults standardUserDefaults] objectForKey:@"keyName"];
//unarchiving object to nsdata
Catalog *selectedCatalog = [NSKeyedUnarchiver unarchiveObjectWithData: nsData];

Hope this helps!

Upvotes: 0

勇敢的心
勇敢的心

Reputation: 341

You must implement for your own object such as:

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInt:self.age forKey:@"age"];
    [aCoder encodeObject:self.email forKey:@"email"];
    [aCoder encodeObject:self.password forKey:@"password"];
}
BOOL success = [NSKeyedArchiver archiveRootObject:person toFile:archiveFilePath];

and:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntForKey:@"age"];
        self.email = [aDecoder decodeObjectForKey:@"email"];
        self.password = [aDecoder decodeObjectForKey:@"password"];
    }
    return self;
}
Person *unarchivePerson = [NSKeyedUnarchiver unarchiveObjectWithFile:archiveFilePath];

Upvotes: 22

Bijoy Thangaraj
Bijoy Thangaraj

Reputation: 5546

You can convert any object to NSData with the NSCoding protocol.

You can find sample code to do this here:
http://samsoff.es/posts/archiving-objective-c-objects-with-nscoding

Upvotes: 1

node ninja
node ninja

Reputation: 32986

Instead of

NSData *dataOnObject = [NSKeyedArchiver archivedDataWithRootObject:classObject];

it should be

NSData *dataOnObject = [[NSUserDefaults standardUserDefaults] objectForKey:@"someKey"];

But that's just for reading data in that's already been saved. If you want to save an object as NSData then you have this:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:classObject] forKey:@"someKey"];

But that's not all. Your classObject has to implement the NSCoding protocol and have the two methods encodeWithCoder: and initWithCoder: since it's not an NS object in order for it to work.

Upvotes: 6

Jonathan del Strother
Jonathan del Strother

Reputation: 2562

You need to implement encodeWithCoder: on your custom class, serializing all of its attributes using the NSCoder passed into it. If its attributes include any more custom classes, they'll need encodeWithCoder: implementing too.

Upvotes: 7

newacct
newacct

Reputation: 122439

you can only archive objects that support the NSCoding protocol

Upvotes: 5

Related Questions