Re: quick and dirty NSData implosion
Re: quick and dirty NSData implosion
- Subject: Re: quick and dirty NSData implosion
- From: Graham Cox <email@hidden>
- Date: Tue, 12 May 2009 11:11:17 +1000
On 12/05/2009, at 6:20 AM, jon wrote:
@property(readwrite, assign) int bookMarkCount;
@property(readwrite, assign) NSString *bookMarkurlString;
@property(readwrite, assign) NSString *bookMarkTitle;
'assign' means the property is a simple assignment, such as ivar =
foo; Therefore your strings are not going to end up owned by the
bookmark object.
You want @property(retain) NSString* bookMarkTitle;
- (id)initWithCoder:(NSCoder *)c
{
[super init];
You do not and should not call [super init] here. In this case it's
harmless as it happens, but in the general case it's not. The only
thing initWithCoder is obliged to call is super's -initWithCoder: and
ONLY when the object is not an immediate subclass of NSObject. In this
case it is, so you should remove this line.
bookMarkCount = [c decodeIntForKey:@"bookMarkCount"];
bookMarkurlString = [c decodeObjectForKey:@"bookMarkurlString"];
bookMarkTitle = [c decodeObjectForKey:@"bookMarkTitle"];
return self;
Even if you fixed your property declarations, this is still not
retaining the strings returned by the coder because you are assigning
the ivars directly. The coder, in accordance with standard memory
management rules, returns objects that you do not own, so if you wish
to take ownership of them, they must be retained. The easiest way to
ensure this is to declare the properties correctly, then use the
accessors, so in -initWithCoder: you should do:
[self setBookMarkTitle:[coder decodeObjectForKey:@"blahblah"]];
So the reason that your strings are going missing is that they're not
retained. When they are subsequently released by the objects that do
own them (most likely an autorelease pool) your references are stale
and no longer point to anything meaningful.
- (void)encodeWithCoder:(NSCoder *)c
{
[c encodeInt:bookMarkCount forKey:@"bookMarkCount"];
[c encodeObject:bookMarkurlString forKey:@"bookMarkurlString"];
[c encodeObject:bookMarkTitle forKey:@"bookMarkTitle"];
}
This is OK, but again it is probably advisable to use the property
getter, since you have one:
[coder encodeObject:[self bookMarkTitle] forKey:@"blahblah"];
Then, if you change the way the title is implemented (using a format
string, say) the archiving code doesn't need to be rewritten. There
are times that you would deliberately want to ensure only the ivar was
written, but those cases tend to be the exception, not the rule.
--Graham
_______________________________________________
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