SundayMonday
SundayMonday

Reputation: 19757

Trouble with shadowing @property in objective-c

Why isn't a setter synthesized for myString in the example below? The basic assignment below results in myString being nil. Trying to use the setter [self setMyString:s]; results in an unrecognized selector exception.

// in .h file
@interface MyClass
@property (nonatomic, readonly) NSString *myString;
@end

// in .m file
@interface MyClass (MyCategory)
@property (nonatomic, copy) NSString *myString;
@end

@implementation MyClass
@synthensize myString;

- (void) someMethod:(NSString *) s {
    myString = [s copy];

    // why is myString nil here?
}

@end

Edit: the problem was with gdb. po myString printed Can't print description of a NIL object.. However NSLog(@"myString: %@", myString); printed the expected value.

Upvotes: 1

Views: 141

Answers (3)

Andrew Madsen
Andrew Madsen

Reputation: 21383

The other two answers are correct, but I think they miss your intention. It's common to declare a property as read-only in the .h file, so that code outside the class implementation can't write it. Inside the .m file, you want it to be readwrite. This kind of redefinition is explicitly supported. However, you need to put the redeclaration as readwrite in a class-extension:

// In your .h file:
@interface MyClass : NSObject
    @property (nonatomic, copy, readonly) NSString *myString;
@end

// In your .m file:
@interface MyClass () // Note the empty parentheses
    @property (nonatomic, copy, readwrite) NSString *myString;
@end

You do still need to use self.myString = aString or [self setMyString:aString], instead of writing to the ivar directly as you're doing right now.

Upvotes: 4

mipadi
mipadi

Reputation: 411252

It looks like you're trying to declare a publicly readonly, privately writable property. You should do that in a class extension rather than a category. Syntactically, a class extension looks like a category with no name:

@interface MyClass ()
@property (nonatomic, copy) NSString *myString;
@end

Upvotes: 4

Caleb
Caleb

Reputation: 125037

Declaring a property with the same name in both your MyClass interface and your MyCategory category seems like a bad idea. Remove the declaration in the category and I expect all will be well.

Upvotes: 1

Related Questions