Marci-man
Marci-man

Reputation: 2233

Implementing NSCoding protocol to send object over to the Java based server

I have asked a similar question a couple of days ago...
While I have made some progress, I still cant seem to make it work.

Here is what I got up till now:

customWriteableObj.h:

@interface customWriteableObj : NSObject <NSCoding>
@property int integer;
@property NSString * string;
@property BOOL boo;
@end

customWriteableObj.m:

#import "customWriteableObj.h"

@implementation customWriteableObj
-(id)init
{
    _integer = 117;
    _string = @"aString";
    _boo = YES;
    return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
    _integer = [aDecoder decodeIntForKey:@"integer"];
    _boo = [aDecoder decodeBoolForKey:@"boo"];
    _string = [aDecoder decodeObjectForKey:@"string"];
    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.string forKey:@"string"];
    [aCoder encodeBool:self.boo forKey:@"boo"];
    [aCoder encodeInteger:self.integer forKey:@"integer"];
}
@end

main:

customWriteableObj * x = [[customWriteableObj alloc]init];
    NSMutableData *dat = [[NSMutableData alloc] init];
    NSKeyedArchiver* arch1 = [[NSKeyedArchiver alloc]initForWritingWithMutableData:dat];
    arch1.outputFormat = NSPropertyListXMLFormat_v1_0;
    [arch1 encodeObject:x forKey:@"tester1"];
    [arch1 finishEncoding];

    [dat writeToFile:@"text.xml";
    customWriteableObj * y = [[customWriteableObj alloc]init];
    y = [NSKeyedUnarchiver unarchiveObjectWithFile:@"text.xml";

Output in XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>$archiver</key>
    <string>NSKeyedArchiver</string>
    <key>$objects</key>
    <array>
        <string>$null</string>
        <dict>
            <key>$class</key>
            <dict>
                <key>CF$UID</key>
                <integer>3</integer>
            </dict>
            <key>boo</key>
            <true/>
            <key>integer</key>
            <integer>117</integer>
            <key>string</key>
            <dict>
                <key>CF$UID</key>
                <integer>2</integer>
            </dict>
        </dict>
        <string>aString</string>
        <dict>
            <key>$classes</key>
            <array>
                <string>customWriteableObj</string>
                <string>NSObject</string>
            </array>
            <key>$classname</key>
            <string>customWriteableObj</string>
        </dict>
    </array>
    <key>$top</key>
    <dict>
        <key>tester1</key>
        <dict>
            <key>CF$UID</key>
            <integer>1</integer>
        </dict>
    </dict>
    <key>$version</key>
    <integer>100000</integer>
</dict>
</plist>

which doesnt seem to be correct, since I cant see any data here, plus, when I try to read it back I get a nil!
I also need to persist this object to a database on a java based server...

Upvotes: 0

Views: 1176

Answers (2)

Dima
Dima

Reputation: 23634

At a glance it looks like you are missing the super calls in your init methods. This means you overrode these initialization methods and never actually initialize an object. So when you deserialize you would just end up with nil. This should fix it:

-(id)init
{
   if(self = [super init])
   {
        _integer = 117;
        _string = @"aString";
        _boo = YES;
   }
   return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    if(self = [self init])
    {
        _integer = [aDecoder decodeIntForKey:@"integer"];
        _boo = [aDecoder decodeBoolForKey:@"boo"];
        _string = [aDecoder decodeObjectForKey:@"string"];
    }
    return self;
}

EDIT with JSON serialization example

Create a method on your custom object class that converts the object into a serializable dictionary. It might look something like:

- (NSDictionary *) jsonDictionary
{
    return @{@"integer": @(_integer), @"boo": @(_boo), @"string" : _string};
}

Then just call that iteratively on all the objects in your array whenever you are ready to send them over. That might look something like:

// Assuming you have an NSArray called customObjects

NSMutableArray *customObjectsJSON = [[NSMutableArray alloc] initWithCapacity:customObjects.count];
for(customWriteableObj *object in customObjects)
{
    [customObjectsJSON addObject:[object jsonDictionary]];
}

At this point, customObjectsJSON is ready to be set as a parameter for a network request. Depending on what other tools you are using you may need to convert it to JSON yourself using NSJSONSerialization

Upvotes: 1

Wain
Wain

Reputation: 119031

It looks correct. In the XML you can see your 117 and aString values. The XML is a custom format so you generally shouldn't be trying to use it for anything other than storing and reloading.

Your result object when you try to load the archive back in is nil because you are reloading differently than you are archiving (in terms of structure). If you are archiving with [arch1 encodeObject:x forKey:@"tester1"]; then you need to unarchive with initForReadingWithData: and decodeObjectForKey:.

Upvotes: 1

Related Questions