views:

605

answers:

3

I have data object class:

@interface Item: NSObject {
    NSString *title;
    NSString *text;
}

@property (copy) NSString *title;
@property (copy) NSString *text;

@end

@implementation Item

@synthesize text;

- (void)updateText {
    self.text=@"new text";
}

- (NSString *)title {
    return title;
}

- (void)setTitle:(NSString *)aString {
    [title release];
    title = [aString copy];
}

@end

I can set the title property just fine when using non-synthesized methods, but when I set a property with synthesized accessors I get an error in the updateText method on the line that reads:

self.text=@"new text";

The error is:

*** NSInvocation: warning: object 0x462d2c0 of class '_NSZombie_CFString' does not implement methodSignatureForSelector: -- trouble ahead
*** NSInvocation: warning: object 0x462d2c0 of class '_NSZombie_CFString' does not implement doesNotRecognizeSelector: -- abort

Why do identical non-synthesized accessors work and synthesized ones don't?

The object is created in main thread and Error appears when it's accessed from NSOperation thread.

A: 

The code you posted works just fine for me. Is there something different between this code and the actual code you are using?

The error messages you are seeing make reference to "zombies", which are pointers to objects that have already been released. Nothing in this code shows any risk of such behaviour, which leads me to think that the actual error is elsewhere.

One possible solution would be to use Xcode's debugger to see the addresses of your NSString objects, and use that information to determine which one eventually results in the NSInvocation warning.

e.James
The object is created in main thread and Error appears when it's accessed from NSOperation thread.
Rod
+3  A: 

The setter should be coded this way:

[title autorelease]
title = [aString copy];

Otherwise another thread may get a title object released under its feet.

Or choose any other consistent accessor style from the Memory Management Programming Guide for Cocoa

IlDan
There is no need to waste doing an autorelease for this. The standard code for a setter simply defends against pointer equality of the new and old title. if ( title != aString ) { [title release]; title = [aString copy]; }
Peter N Lewis
Be careful: those are strings and we are copying them for a reason. title != aString may get really nasty with mutable strings
IlDan
I prefer the autorelease approach. Less code is better, and 99.9% of the time the performance difference isn't noticeable.
Tom Dalling
A: 

In this code [self setTitle:[self title]] would release and dealloc title before copying it. You need to check if title == aString in the setter.

porneL