views:

156

answers:

2

I simply want to change a variable of an object from another class. I can compile without a problem, but my variable always is set to 'null'. I used the following code:

Object.h:

@interface Object : NSObject {
    //...
    NSString *color;
    //...
}

@property(nonatomic, retain) NSString* color;

+ (id)Object;
- (void)setColor:(NSString*)col;
- (NSString*)getColor;
@end

Object.m:

+(id)Object{
    return [[[Object alloc] init] autorelease];
}

- (void)setColor:(NSString*)col {
    self.color = col;
}

- (NSString*)getColor {
    return self.color;
}

MyViewController.h

#import "Object.h"

@interface ClassesTestViewController : UIViewController {
    Object *myObject;
    UILabel *label1;
}

@property UILabel *label1;
@property (assign) Object *myObject;
@end

MyViewController.m:

#import "Object.h"
@implementation MyViewController
@synthesize myObject;

- (void)viewDidLoad {
    [myObject setColor:@"red"];
    NSLog(@"Color = %@", [myObject getColor]);
    [super viewDidLoad];
}

The NSLog message is always Color = (null)

I tried many different ways to solve this problem, but no success. Any help would be appreciated.

+3  A: 
  1. You're declaring a property, then explicitly declaring the accessors in Object.h. You only need to do one or the other - they mean the same thing (well, almost - you'll have color instead of getColor)
  2. To implement the property in Object.m you should use @synthesize color. The explicit implementations, again, are then redundant (unless they do anything extra).
  3. The explicit setColor implementation in Object.m is calling the property - which you are implementing explicitly, so I would have expected you to get an infinite recursion here.
  4. MyViewController.m should probably synthesize label1, since you declare the property in the header (although it's not being used in your snippet).
  5. [myObject getColor] is calling the color property, which you declared but did not synthesize. If you had explicitly implemented it as color it would have picked that up - but it won't match getColor (which is fortunately as that would have led to an infinite recursion again.
  6. I don't see anywhere where you create your myObject instance. If you don't it will be nil and methods called on it (including property accesses) will return 0 or nil.

I suspect (6) is the cause of your issue, but the others need to be addressed too. Make sure you read up on property syntax.

Phil Nash
And the use of `@synthesize myObject;` suggests a misunderstanding about creating object instances vs. synthesizing property accessors. +1 for the idea of reading up on property syntax.
David Gelhar
...and here's a link to the reference: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html
jlehr
It's also generally a bad idea to begin a method name with a capital letter, as you've done with the +Object method.
jlehr
A: 

Thanks for the help so far.

I modified the code as follow, but it still doesn't work as it should.

MyViewController.h:
    #import <UIKit/UIKit.h>
    #import "Object.h"

    @interface MyViewController : UIViewController {
        Object *myObject;
    }
    @property (nonatomic, retain) Object *myObject;
    @end

MyViewController.m:

#import "MyViewController.h"
#import "Object.h"

@implementation MyViewController
@synthesize myObject;

- (void)viewDidLoad {
Object *myObject = [Object new];
myObject = 0;
[myObject setColor:@"red"];
NSLog(@"color = %@", myObject.color);
[super viewDidLoad];
}

If I do it like this, NSLog returns color = null (and I think myObject is only visible in viewDidLoad). How can declare myObject and make it visible in MyViewController? I stripped down my Object class to

Object.h:

@interface Object : NSObject {
    NSString *color;
}    
@property(nonatomic, retain) NSString *color;
@end

Object.m:

#import "Object.h"
@implementation Object
@synthesize color;
@end

I wasn't able to define an object myObject in ViewDidLoad so that I can access its properties from the whole ViewController class? What did I miss? Side question: Why do I have to set myObject to 0?

Daniel
You should have asked this is a seperate question - or added it to your original.However, two things I notice straight away: `Object *myObject = [Object new];` declares a new, local, variable called myObject that hides the instance variable. Just remove the `Object *` part of that line. The second thing is the `myObject = 0;` line. You asked why you have to do that. You don't! It is wrong to do so. Why do you think you needed to?
Phil Nash
If I don't add `myObject = 0`, it can compile but the program will crash immediately with the following error: `*** NSInvocation: warning: object 0x3e1dcc0 of class 'Object' does not implement doesNotRecognizeSelector: -- abort`When I delete the `Object *` part, I get the same `color = null` error
Daniel
The NSInvocation warning would suggest that a method call is not implemented. Setting it to 0 simply hides that (and causes other problems), because calling a method on a nil object is legal in Obj-C (but will do nothing). I'm wondering if calling your class `Object` is part of the problem. Try calling it something else for now.
Phil Nash
Thank you for the advice!Calling the class `object` probably wasn't my best idea :)
Daniel