1

I've got a doubt about assigning values to properties in Objective-C. I've had a lot of problems of "misteriously missed" values, for example if I have this interface:

// MyClass.h
@interface MyClass : NSObject {
    MyOtherClass *myVar;
}

@property (nonatomic, retain) MyOtherClass *myVar;

- (id)initWithValue:(NSString *)val;

And this implementation:

// MyClass.m
@implementation MyClass

@synthesize myVar;

- (id)initWithValue:(NSString *)val {
    self = [super init];

    if (self != nil) {
        /** Do some stuff with val... **/
        myVar = [method:val]; // Some method that returns a MyOtherClass value
    }

    return self;
}

At some point of the execution, the value of myVar disappears, changes or something else... And the solution is to change:

myVar = [method:val]; // Some method that returns a MyOtherClass value

for

self.myVar = [method:val]; // Some method that returns a MyOtherClass value

So... what is the diference between using self or not using it? I mean, it's clear that I've to use it because if not it will cause problems but I don't know why

Thank you in advance

rai212
  • 711
  • 1
  • 6
  • 20
  • possible duplicate of [Difference between calling self.var vs var](http://stackoverflow.com/questions/4627646/difference-between-calling-self-var-vs-var) – rob mayoff Apr 12 '12 at 21:18

3 Answers3

3

If you use self, you're using the property and it is marked with "retain". If you use the variable, you're bypassing the property, therefore no "retain". You could write myVar = [[someObject method:val] retain]; and get the same effect as the property.

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
1

This is a good example of why you should change your @synthesize to @synthesize myVar = _myVar; or some variation of that. Without doing that, it is possible to set your instance variable out from under you as a direct assignment of `myVar = nil" would bypass your setter.

Using the myVar = _myVar strategy will cause the compiler to complain if you attempt to do myVar = and will require you to call self.myVar which will access your setter or getter.

The only place you should then use _myVar is if you change the declaration of your setter or getter for that variable.

Mike Z
  • 4,121
  • 2
  • 31
  • 53
  • Good, but I do not agree on the last part. There are situations in which it may be more appropriate to use the variable directly. Those being situations where you a) need to worry about performance, since calling the getter/setter is another method call or b) alloc/init an object and want to save the release – Ahti Apr 12 '12 at 21:40
  • 1
    True, but you are only going to notice a performance issue if you are calling your setter or getter repeatedly (many, many, many times) very tight loop. – Mike Z Apr 12 '12 at 21:44
0

What method are you calling on val?

I would imagine that when you do

myVar = [method:val]; // Some method that returns a MyOtherClass value

The result is an autoreleased object. That means that when your init method finishes your myVar object is released and gets destroyed. The myVar variable still points to the place in memory where the object was, but that memory could get filled with anything.

When you use the property setter method using the dot syntax like this

self.myVar = [method:val];

The setter method that is automatically synthesised for you by the compiler will send the object a retain message to keep it around.

You could also fix your code error like this:

myVar = [[method:val] retain]; // Some method that returns a MyOtherClass value

but its better to stick to the dot syntax.

jackslash
  • 8,550
  • 45
  • 56
  • These days, it's best to just assume ARC, in which case this isn't an issue. – BJ Homer Apr 12 '12 at 21:22
  • They're not using ARC, as under ARC you can't use the `retain` keyword for a property . If they were using ARC the equivalent keyword would be `strong` – jackslash Apr 12 '12 at 21:25
  • I agree that the submitter would probably benefit from ARC though – jackslash Apr 12 '12 at 21:25
  • 1
    Incorrect; `retain` is still valid as a property qualifier under ARC. You generally would use `strong` instead of `retain`, but since it appears in a header, and since ARC sources can interact with non-ARC classes (and #import non-ARC headers), `retain` and `strong` are synonymous in property declarations. – BJ Homer Apr 12 '12 at 21:29
  • But reading the question again, it does appear that he may be non-ARC, since he says the value is disappearing on him. – BJ Homer Apr 12 '12 at 21:30
  • well it appears you're right and you can use retain instead of strong. I had assumed as the convert to ARC process changes the keywords. :) Answer in general seems correct though – jackslash Apr 12 '12 at 22:08
  • As @BJHomer says I'm not using ARC (so effectively the value disappears). Thank you every one for your help – rai212 Apr 16 '12 at 06:37