Re: isKindofClass with NSData and NSKeyUnarchiver
Re: isKindofClass with NSData and NSKeyUnarchiver
- Subject: Re: isKindofClass with NSData and NSKeyUnarchiver
- From: Ken Thomases <email@hidden>
- Date: Thu, 27 May 2010 05:36:06 -0500
On May 27, 2010, at 4:21 AM, Philip Vallone wrote:
> I am passing different types of data to NSData (NSString, NSArray, UIImage). I am trying to find out what kind of data t is so I know how to handle the NSData when I receive it.
NSData is just a byte sequence. It doesn't have any knowledge about the semantic meaning of those bytes.
I'm not even sure what you mean by "passing different types of data to NSData". You don't pass strings, arrays, or images to NSData. You can ask some of those objects for data, but that's not the same thing.
> NSString *somedata = [[NSString alloc] initWithString:@"Some string"];
The above is a warning sign. I see it a lot with new Cocoa programmers. The expression
@"Some string"
is already a full-fledged string object. You can send it messages and everything. There's no reason to "turn it into a string object" or "make a string object from it" or anything like that. Creating a new string from it, as you've done with +alloc and -initWithString: accomplishes nothing but a bit of waste.
I only point it out because it indicates a weakness in your understanding of the language and framework.
Also, calling a string "somedata" is just going to confuse you and anybody else reading your code. A string object is not a data object.
> NSData * set = [NSKeyedArchiver archivedDataWithRootObject:[somedata dataUsingEncoding:NSASCIIStringEncoding]];
I don't think this is doing what you want. The expression "[somedata dataUsingEncoding:NSASCIIStringEncoding]" asks the string to create a byte sequence by encoding its contents into ASCII. It puts the byte sequence into a data object and returns it to you. Once again, the data object knows nothing about the semantics of the byte sequence. You can't query it and ask, "were you originally a string?" It doesn't have the slightest clue.
Then, you create another data object by key-archiving the data object with the ASCII byte sequence. That second data object also doesn't know that it's a keyed archive containing a data object (which happens to contain an ASCII byte sequence of a string).
However, it does have internal structure so that an NSKeyedUnarchiver can rediscover that it was a data object. But that still doesn't imbue the unarchived data object with knowledge that it originally came from a string.
The question is, why did you ASCII-encode the string into a data object if you were then going to archive that data object into another data object. I think you probably want to simply archive the string, directly:
NSData* set = [NSKeyedArchiver archivedDataWithRootObject:somedata];
Again, calling a data object a "set" is just confusing.
> NSData * unset = [NSKeyedUnarchiver unarchiveObjectWithData:set];
With your original code, unset would now point to a data object which contains the ASCII byte sequence obtained from the string. Still, though, this data object has no way of knowing that its contents are ASCII-encoded characters or that it came from a string.
> NSLog(@"Class Type %@", [unset isKindOfClass:[NSKeyedUnarchiver class]]);
Alexander has already pointed out the problems with this line. But, more fundamentally, there's no amount of querying of the unarchived data object that will reveal what it once was. It doesn't know. You'll only learn that it is a data object.
If you had originally archived the string object instead of a data object obtained by asking the string to encode itself, then you would have gotten back an equivalent string object. You could usefully ask that string object about its class using -isKindOfClass:.
To summarize, perhaps this does what you're looking for:
NSString* somestring = @"Some string";
NSData* archive = [NSKeyedArchiver archivedDataWithRootObject:somestring];
// ... later ...
id obj = [NSKeyedUnarchiver unarchiveObjectWithData:archive];
if ([obj isKindOfClass:[NSString class]])
// ... use 'obj' as a string
else if ([obj isKindOfClass:[NSArray class]])
// ... use 'obj' as an array
// ... etc. ...
(Note that I don't release somestring because I don't own it, by the memory management rules. You were correct to release yours, though, since your code did own its.)
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden