Update - Many people are insisting I need to declare an iVar for the property. Some are saying not so, as I am using Modern Runtime (64 bit). I can confirm that I have been successfully using @property without iVars for months now. Therefore, I think the 'correct' answer is an explanation as to why on 64bit I suddenly have to explicitly declare the iVar when (and only when) i'm going to access it from a child class. The only one I've seen so far is a possible GCC bug (thanks Yuji). Not so simple after all... To clarify the possible bug is this: When inheriting from a base class, a child can not access the parent's iVar IF that child also happens to implement an UNRELATED accessor using @synthesize BEFORE the iVar is accessed.
I've been scratching my head with this for a couple of hours - I haven't used inheritance much.
Here I have set up a simple Test B class that inherits from Test A, where an ivar is declared. But I get the compilation error that the variable is undeclared. This only happens when I add the property and synthesize declarations - works fine without them.
TestA Header:
#import <Cocoa/Cocoa.h>
@interface TestA : NSObject {
NSString *testString;
}
@end
TestA Implementation is empty:
#import "TestA.h"
@implementation TestA
@end
TestB Header:
#import <Cocoa/Cocoa.h>
#import "TestA.h"
@interface TestB : TestA {
}
@property (nonatomic, retain) NSString *testProp;
@end
TestB Implementation (Error - 'testString' is undeclared)
#import "TestB.h"
@implementation TestB
@synthesize testProp;
- (void)testing{
NSLog(@"test ivar is %@", testString);
}
@end
I just ran into that same problem but the sources were complex enough that I didn't quite understand what made iVar from the parent inaccessible when I used GCC. I only knew for sure that a few months ago and before changes in my code it worked and also that it is working with clang which I've been using for a while. Suddenly I had to build with GCC and it wouldn't anymore.
At least this article gave me a bypass (declare the iVars). I am surprised that the latest version of XCode does not include a fixed compiler
I'm seeing
error: 'testString' undeclared (first use in this function)
when the@synthesize
is just before thetesting
method. The error disappears if I move the@synthesize
below the method implementation. This might be because the TestB class doesn't have atestProp
string instance variable to use with the declared property. (In the Legacy (32-bit) runtime, you must declare instance variables to use for properties — in Modern runtime (64-bit Mac, iPhone) they can be inferred, so declaring them is optional.) Is it possible that you meant to name the propertytestString
instead?EDIT: In GCC 4.2, it works if you change TestB.h to the following:
However, using the Clang-LLVM compiler, the code works unmodified. Perhaps this is a bug to file.
I think you just have a typo - it should be "testString" not "test"
I think this is the bug of GCC 4.2.1. I made the file
foo.m
with the contentNote that it's OK in the 64 bit mode to omit the instance variable. My GCC 4.2.1 on OS X 10.6.3 gave me an error:
This compiled without problem by changing
to
Clang compiled it without any problem.
( In the 32 bit mode, I got
which is a perfectly expected behavior, as Manjunath wrote.)
However I think it's generally a rather bad idea to access an instance variable of the superclass: when you implement the methods the superclass, you cannot assume anything about the instance variable because it might be tweaked in a worst manner possible by the subclass. You at least need to write down what kind of operation on the instance variable is permitted or not... Remember you might need to maintain your code for years! I would prefer keeping programming contracts between various parts of the code at the level of methods and properties.
Finally you should change
to
or at least to
if you're not using GC on OS X. Otherwise EXP_BAD_ACCESS will await you!