Crystal
Crystal

Reputation: 29458

Error accessing generated ivars when I override setters and getters in Modern Objective-C

I know now the new Objective-C compiler lets you not need to synthesize your properties anymore. I have one file that has two classes in it. My .h for a simple helper class looks like this:

@interface ViewFrameModel : NSObject

@property (nonatomic, strong) UIView *view;
@property (nonatomic, assign) CGRect frame;

- (id)initWithView:(UIView *)view frame:(CGRect)frame;

@end

In the same .h file, for my other class (class 2), I have:

@property (nonatomic, strong) ViewFrameModel *viewFrameModel;

In class 2.m, I can do this:

- (void)setViewFrameModel:(ViewFrameModel *)viewFrameModel {
    _viewFrameModel = viewFrameModel;        
    [self pushViewFrameModel:viewFrameModel];
}

This works fine with no complaints from the compiler, however, when I add this:

- (ViewFrameModel *)viewFrameModel {
    return _viewFrameModel;
}

I get two complaints, one on the first method setViewFrameModel:

"Use of undeclared identifier _viewFrameModel, did you mean viewFrameModel"

And the other on return _viewFrameModel:

"Use of undeclared identifier _viewFrameModel, did you mean viewFrameModel" "Reference to local variable viewFrameModel' declared in enclosing context"

Why do I get these errors when I add in the

- (ViewFrameModel *)viewFrameModel {
    return _viewFrameModel;
}

method? I want to override this method with some custom info, but it's complaining at me :-. Thoughts? TIA.

Upvotes: 21

Views: 3520

Answers (3)

kgaidis
kgaidis

Reputation: 15589

To summarize the answers:

If you override both the setter and the getter, the compiler will not create the instance variable for you.

Why? In that case, the compiler assumes that the property is dynamic: that it might be a property that relies on other properties for storage / computation, or that it will be created in other ways, for example, at runtime using Objective-C runtime functions.

To help the compiler understand the situation better there are two potential solutions:

@implementation Class
@synthesize property = _property;
...
@end

or

@implementation Class {
    PropertyClass *_property;
}
...
@end

Upvotes: 3

Jeffery Thomas
Jeffery Thomas

Reputation: 42588

Here is the results of some testing I did last year: iOS automatic @synthesize without creating an ivar.

In short, you need to use @synthesize or declare an iVar explicitly.

Upvotes: 5

Carl Veazey
Carl Veazey

Reputation: 18363

If you override both the setter and the getter, the compiler will not automatically create the instance variable for you anymore. You can add it to your class implementation like so:

@implementation ClassName {
    ViewFrameModel *_viewFrameModel;
}
...
@end

Upvotes: 35

Related Questions