Brenden
Brenden

Reputation: 7908

Why isn't the instance variable declared?

I'm using xcode 4.5.2 and LLVM 4.1. I am expecting that I do not need to synthesize a class property nor declare an instance variable, but I'm getting errors stating that these expectations are wrong.

My class:

@interface Test : NSManagedObject
@property (strong, nonatomic) NSString *string;
@property (strong, nonatomic) NSString *number;
@end

@implementation Test
- (NSString*)string {
    return _string;
}
@end

1) Use of undeclared identifier 'string'

I've also seen in WWDC 2010 Session 144 the following:

return self->string;

But that is giving an error with a suggestion to use dot notation.

2) Property 'string' found on object of type 'Test *'; did you mean to access it with the "." operator?

I'm also getting a warning for number:

3) Property 'number' requires method 'number' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation

I am entirely lost as to what is going on here. It's starting to boil my blood just a little bit. What am I missing?

Upvotes: 1

Views: 1914

Answers (2)

MishieMoo
MishieMoo

Reputation: 6680

First of all, dot notation is your friend!

Secondly, when you try to use -> you must access the ivar. In the newest versions of Xcode and LLVM, an ivar with an underscore is created for you if you do not specify one yourself using @synthesize.

So you would do self->_string. You access the property when you use the . which is recommended. This also is probably why you're getting a warning on number, since self->number doesn't exist.


Edit: In response to the fact that you're using NSManagedObject I'd definitely recommend using properties (like Todd recommended). NSManagedObjects expect you to use @dynamic and since Core Data does a lot of stuff under the hood, Apple recommends you not change that.

If you want a custom getter/setter, I defer to another SO question which uses the primitive methods:

- (NSString *)name
{
    [self willAccessValueForKey:@"name"];
    NSString *myName = [self primitiveName];
    [self didAccessValueForKey:@"name"];
    return myName;
}

And of course, Apple Docs on the matter. And a related question/solution that pertains to iOS 6.

Upvotes: 5

jrturton
jrturton

Reputation: 119242

If you implement both a setter and a getter method for a property, then the compiler assumes you're also taking care of the backing storage and will not create the _string instance variable for you.

You can either declare it yourself manually, or use @synthesize string = _string; force the compiler to declare it for you. The latter will give the ivar the right memory management semantics (strong, weak etc) based on the property type.

For managed objects, you need to implement MishieMoo's answer, but this is the cause of your NSObject subclass not having a _string variable as stated in the question.

It is covered in more detail here

Upvotes: 2

Related Questions