views:

39

answers:

3

I have been trying to set up an instance property of a class which is itself a class that contains instance variables. I would like to access these as properties. In C#, this is easy to do with the pre-set get and set variables:

public class TheOverallClass
{
    private ClassName _propertyName;
    public ClassName PropertyName
    {
        get { return _propertyName; }
        set { _propertyName = value; }
    }

...and PropertyName being instantiated within the constructor:

    public TheOverallClass()
    {
        PropertyName = new ClassName();
    }
}

Say PropertyName had an instance variable/property named ThisValue, I could then access it as:

TheOverallClass overallClass = new TheOverallClass();
overallClass.PropertyName.ThisValue = 20;    // int
Console.WriteLine(overallClass.PropertyName.ThisValue.ToString());

How would I go about doing this in Objective-C? I have had a go, but have run into difficulty.

The PropertyName equivalent is coded as:

... in AnotherClass.h:

@interface AnotherClass : NSObject {
    int thisValue;
}
@property (readwrite,assign) int ThisValue;
@end

... and in AnotherClass.m

@implementation AnotherClass
@synthesize ThisValue=thisValue;
@end

This is then used in the ClassName equivalent, MyClass:

... in MyClass.h:

@class AnotherClass;
@interface MyClass : NSObject {
    AnotherClass* another;
}
@property (nonatomic,retain) AnotherClass* Another;
@end

... and in MyClass.m:

@implementation MyClass
@synthesize Another=another;
@end

When I try to get/set values within code, Xcode returns "Accessing unknown 'ThisValue' component of a property". The code I use to access is:

MyClass* me = [[MyClass alloc] init];
me.Another.ThisValue = 20;
NSLog(@"Value = %i", me.Another.ThisValue);

What am I doing wrong?

A: 

Do you include AnotherClass.h in the file that contains the me.Another.ThisValue = 20;? If not, it won't know how to handle the Another class.

(Also, upper case initials is usually reserved for constants and class names, as opposed to how it is in C#.)

calmh
I didn't add the header file. Have done so now - thanks!
BWHazel
A: 

Your code should work:

// main.m


#import <Foundation/Foundation.h>

@interface AnotherClass : NSObject {
    int thisValue;
}
@property (readwrite,assign) int ThisValue;
@end

@implementation AnotherClass
@synthesize ThisValue=thisValue;
@end

@interface MyClass : NSObject {
    AnotherClass* another;
}
@property (nonatomic,retain) AnotherClass* Another;
@end

@implementation MyClass
@synthesize Another=another;
@end


int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...

    MyClass* me = [[MyClass alloc] init];
    me.Another.ThisValue = 20;
    NSLog(@"Value = %i", me.Another.ThisValue);


    [pool drain];
    return 0;
}

Disregarding coding conventions aside, this code compiles and runs just fine.

Eiko
The code compiles and runs, but the values in NSLog do not appear. It appears, however, I hadn't allocated or initialised the AnotherClass instance.
BWHazel
A: 

Assuming the code that's accessing the property is in main.m, al calmh mentioned, you would need an import statement for the class that declares the property ( in this case, AnotherClass.h). But your code still won't work the way you expect, because it never creates the nested instance of AnotherClass. Try this:

MyClass* me = [[MyClass alloc] init];
me.Another = [[AnotherClass alloc] init];
me.Another.ThisValue = 20;
NSLog(@"Value = %i", me.Another.ThisValue);

Then do yourself a favor, and don't change the property names in your @synthesize statements. Instead of doing this...

@synthesize ThisValue=thisValue;

...just do this...

@synthesize thisValue;

...and then rewrite the code in main like this...

MyClass* me = [[MyClass alloc] init];
me.another = [[AnotherClass alloc] init];
me.another.thisValue = 20;
NSLog(@"Value = %i", me.another.thisValue);
jlehr
Thank you - this is where it was falling over! Added [[AnotherClass alloc] init] and the code fully works!I also tried and managed to override the init method and get the AnotherClass allocated and initialised within it.
BWHazel