FROM : Ricky Sharp
DATE : Wed Apr 06 13:13:34 2005
On Wednesday, April 06, 2005, at 02:37AM, <<email_removed>> wrote:
>Hey there. I have a simple doc-based app that manages a single model object. The model object implements NSCoding and also overrides initWithCoder and encodeWithCoder. I then use an NSKeyedArchiver in MyDocument to archive the object to disk (archiveDataWithRootObject) in dataRepresentationOfType. Also use an NSKeyedUnarchiver to unarchive the model object back (unarchiveObjectWithData) in loadDataRepresentation:ofType:.
>
>My interface elements are properly bound to my model object instance variables. But when I try to "open" a file that I previously saved, I get the following from the Log window twice:
>
>[TradeModel copyWithZone:]: selector not recognized [self = 0x3ee2e0]
copyWithZone: belongs to the NSCopying protocol and not NSCoding. Sometimes you have to provide copyWithZone.
>Now, two of my model instances are int primitives, and I was encoding and decoding using NSNumber class methods, like so:
>
>- (void)encodeWithCoder:(NSCoder*)coder
>{
> [coder encodeObject:[NSNumber numberWithInt:[self tradeTypeValue]]];
> [coder encodeObject:[NSNumber numberWithInt:[self tradeStatusValue]]];
> [coder encodeObject:[self traderName]]; // NSString var
> [coder encodeObject:[self traderAddress]]; // NSString var
>}
If TradeModel's superclass conforms to NSCoding, you'll need to call super's encodeWithCoder before you encode your ivars.
Also, there's no need to wrap non-object ivars (e.g. int with NSNumber). Look at using encodeValueOfObjCType instead. Or, if you're able to use NSKeyedArchiver, look into using encodeObject:forKey:, encodeInt:forKey:, etc. This will shield you from having to encode/decode in a particular order.
>
>(id)initWithCoder:(NSCoder*)coder
>{
> [super init];
> [self setTradeTypeValue:[[coder decodeObject] intValue]];
> [self setTradeStatusValue:[[coder decodeObject] intValue]];
> [self setTraderName:[coder decodeObject]];
> [self setTraderAddress:[coder decodeObject]];
> return self;
>}
Again, if the superclass conforms to NSCoding, you'll need to call super's initWithCoder.
Also, this method should really be implemented something like this:
if ((self = [super init]) != nil) // or initWithCoder:
{
// set ivars
}
return self;
And, if you can use NSKeyedUnarchiver, look at using decodeObjectForKey:, decodeIntForKey:, etc.
--
Rick Sharp
Instant Interactive(tm)
DATE : Wed Apr 06 13:13:34 2005
On Wednesday, April 06, 2005, at 02:37AM, <<email_removed>> wrote:
>Hey there. I have a simple doc-based app that manages a single model object. The model object implements NSCoding and also overrides initWithCoder and encodeWithCoder. I then use an NSKeyedArchiver in MyDocument to archive the object to disk (archiveDataWithRootObject) in dataRepresentationOfType. Also use an NSKeyedUnarchiver to unarchive the model object back (unarchiveObjectWithData) in loadDataRepresentation:ofType:.
>
>My interface elements are properly bound to my model object instance variables. But when I try to "open" a file that I previously saved, I get the following from the Log window twice:
>
>[TradeModel copyWithZone:]: selector not recognized [self = 0x3ee2e0]
copyWithZone: belongs to the NSCopying protocol and not NSCoding. Sometimes you have to provide copyWithZone.
>Now, two of my model instances are int primitives, and I was encoding and decoding using NSNumber class methods, like so:
>
>- (void)encodeWithCoder:(NSCoder*)coder
>{
> [coder encodeObject:[NSNumber numberWithInt:[self tradeTypeValue]]];
> [coder encodeObject:[NSNumber numberWithInt:[self tradeStatusValue]]];
> [coder encodeObject:[self traderName]]; // NSString var
> [coder encodeObject:[self traderAddress]]; // NSString var
>}
If TradeModel's superclass conforms to NSCoding, you'll need to call super's encodeWithCoder before you encode your ivars.
Also, there's no need to wrap non-object ivars (e.g. int with NSNumber). Look at using encodeValueOfObjCType instead. Or, if you're able to use NSKeyedArchiver, look into using encodeObject:forKey:, encodeInt:forKey:, etc. This will shield you from having to encode/decode in a particular order.
>
>(id)initWithCoder:(NSCoder*)coder
>{
> [super init];
> [self setTradeTypeValue:[[coder decodeObject] intValue]];
> [self setTradeStatusValue:[[coder decodeObject] intValue]];
> [self setTraderName:[coder decodeObject]];
> [self setTraderAddress:[coder decodeObject]];
> return self;
>}
Again, if the superclass conforms to NSCoding, you'll need to call super's initWithCoder.
Also, this method should really be implemented something like this:
if ((self = [super init]) != nil) // or initWithCoder:
{
// set ivars
}
return self;
And, if you can use NSKeyedUnarchiver, look at using decodeObjectForKey:, decodeIntForKey:, etc.
--
Rick Sharp
Instant Interactive(tm)
| Related mails | Author | Date |
|---|---|---|
| <java_nutt | Apr 6, 09:37 | |
| Ricky Sharp | Apr 6, 13:13 | |
| <java_nutt | Apr 6, 13:48 | |
| Ricky Sharp | Apr 6, 15:00 | |
| Kevin Callahan | Apr 9, 06:42 |






Cocoa mail archive

