I can’t access member variables of a sub class after sending object as super class. Member functions are working. See this example:
super class definition
@interface SuperClass : NSObject {
NSString *stringSuper;
NSInteger intSuper;
}
- (void)test; // NSLog(@"test: SuperClass");
derived class definition
@interface DerivedClass : SuperClass {
NSString *stringDerived;
NSInteger intDerived;
}
- (void)test; // NSLog(@"test: DerivedClass");
- (void)test1; // NSLog(@"test1: DerivedClass");
create a DerivedClass object and send as SuperClass
DerivedClass *d = [[DerivedClass alloc] init];
d.stringSuper = anotherString;
d.intSuper = anotherInt;
d.stringDerived = anotherString1;
d.intDerived = anotherInt1;
[anObject sendMessage:d];
try to access members after cast to DerivedClass
- (void)sendMessage:(SuperClass *)s {
DerivedClass *d = (DerivedClass *)s;
NSLog(@"%@", d.stringSuper); // ok
NSLog(@"%d", d.intSuper); // ok
NSLog(@"%@", d.stringDerived); // EXC_BAD_ACCESS
NSLog(@"%d", d.intDerived); // ok
[d test]; // ok ("test DerivedClass")
[d test1]; // ok ("test1 DerivedClass")
}
I’ve declared @properties (nonatomic, assign) for all members. The debugger shows me the correct address for stringDerived, but it is “out of scope”.
Does anybody know what is the reason for this behavior?
Thanks, rodo
Yes: you have violated rule 1 of how to do properties. Clearly
anotherString1was released before the point you read from d.stringDerived; it may even have been invalid at the point you set d.stringDerived. Equally,anotherStringis obviously either a constant string or retained by something else. It would have been more obvious if you had shown your actual code.If you define a class with an object-type property you must arrange for instances of your class to copy or retain the value assigned to that property in order to be assured that it will still be there when you next look. If you use assign the value will probably become invalid very quickly as it is likely to be an autoreleased value. In general, if the property type conforms to the NSCopying protocol and it is mutable or has a mutable subclass (for example: NSString, NSData, NSSet, NSArray, etc) it is best to use copy so that the value doesn’t change once set; in other cases it is fine to use retain.
Having done this you must also ensure that the memory used by the property value is correctly accounted-for when the object is deallocated. Set the value of any object-type properties to nil in your dealloc routine.