Skip to content

Custom type mappings Custom classes

nesium edited this page Sep 13, 2010 · 1 revision

I’ve sent a full-fledged object and all I got was this lousy ASObject!

Let’s say you have a custom object which is returned by your webservice and looks like this:

Class Book
- String title
- String publisher
- Number year

1. Working with ASObjects

ASObjects are key-value compliant. That means you can use them like any other dictionary:

ASObject *book = [AMFUnarchiver unarchiveObjectWithData:myAMFData encoding:kAMF3Version];
NSLog(@"title: %@, year: %d", [book valueForKey:title], [[book valueForKey:year] intValue]);

2. Using custom classes without registering

Alternatively you could have a class around which is also named Book. Now you’re responsible for decoding the object yourself, by implementing the NSCoding protocol. You’re class would look like this:

@interface Book : NSObject
{
	NSString *title;
	NSString *publisher;
	NSNumber *year;
}
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *publisher;
@property (nonatomic, retain) NSNumber *year;
@end

@implementation Book

@synthesize title, publisher, year;

- (id)initWithCoder:(NSCoder *)coder
{
	if (self = [super init])
	{
		self.title = [coder decodeObjectForKey:@"title"];
		self.publisher = [coder decodeObjectForKey:@"publisher"];
		self.year = [coder decodeObjectForKey:@"year"];
	}
	return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
	[encoder encodeObject:title forKey:@"title"];
	[encoder encodeObject:publisher forKey:@"publisher"];
	[encoder encodeObject:year forKey:@"year"];
}
@end

Now you’re class is ready to be serialized and deserialized from and to AMF.

3. Using custom classes by registering

Imaging you had the very same class Book but you’re a good Cocoa citizen and namespaced your class, so that it’s called MyBook. There would be now way for CocoaAMF to figure out, that Book from your webservice should become MyBook on the client side. That’s why you need to register it, either

Globally

[AMFUnarchiver setClass:[MyBook class] forClassName:@"Book"];
[AMFArchiver setClassName:@"Book" forClass:[MyBook class]];

which will affect every instance of AMFArchiver and AMFUnarchiver. Or you could do it

Locally

AMFUnarchiver *unarchiver = [[AMFUnarchiver alloc] initForReadingWithData:myAMFData encoding:kAMF3Version];
[unarchiver setClass:[MyBook class] forClassName:@"Book"];

which of course will only affect the used unarchiver.

4. Using externalizable classes

Externalizable classes are non-keyed archives in Cocoa context, where they are infrequently used. Nevertheless since externalizable classes are the only way in Flash to control the serialization you’ll might want to use them. So let’s jump back to example 2, but this time with a class which supports its externalized counterpart:

@interface Book : NSObject
{
	NSString *title;
	NSString *publisher;
	NSNumber *year;
}
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *publisher;
@property (nonatomic, retain) NSNumber *year;
@end

@implementation Book

@synthesize title, publisher, year;

- (id)initWithCoder:(NSCoder *)coder
{
	if (self = [super init])
	{
		self.title = [coder decodeObject];
		self.publisher = [coder decodeObject];
		self.year = [coder decodeObject];
	}
	return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
	[encoder encodeObject:title];
	[encoder encodeObject:publisher];
	[encoder encodeObject:year];
}
@end

You see it’s essentially the same and only uses a non-keyed archiver this time. Of course you can call allowsKeyedCoding in order to know whether the AMFUnarchiver/AMFArchiver is in keyed coding mode or not.