8

Does Xcode 4.5 have a slightly different manner of auto-generating properties and their associated memory release sections (in dealloc and viewDidUnload)?

I upgraded to Xcode 4.5 from 4.5 Beta 1 yesterday. Now when I use Interface Builder to create an outlet (by Ctrl-dragging from, say, a UILabel to the associated header file), it creates the @property declaration in the header as normal:

@property (retain, nonatomic) IBOutlet UILabel *propertyName;

However, in the associated .m file, there is no @synthesize declaration.

The code in viewDidUnload is normal:

- (void)viewDidUnload {
    [self setPropertyName:nil];
    [super viewDidUnload];
}

However, the code in dealloc prepends an _ on the property name:

- (void)dealloc {
    [_propertyName release];
    [super dealloc];
}

This also means I cannot reference the property as normal ([propertyName doSomething];)

Did something change? Or did I accidentally coincidentally change some setting?

eattrig
  • 326
  • 1
  • 4
  • 12

5 Answers5

14

Yes, the behavior has changed slightly in Xcode 4.5.

... in the associated .m file, there is no @synthesize declaration.

In Xcode 4.5, the @synthesize statement is now optional, and properties are synthesized automatically. Automatically generated IBOutlet properties therefore no longer add @synthesize because it's no longer required.

... the code in dealloc prepends an _ on the property name

When properties are synthesized automatically (without an explicit @synthesize statement) the corresponding instance variable is prepended with an underscore. That's why it shows up as such in your dealloc method. This is so the instance variable and property names don't overlap.

This also means I cannot reference the property as normal

No. Accessing instance variables and properties has not changed. All that has changed is the default name of the instance variable. E.g.:

_foo = @"Bar"; // Setting an instance variable directly.
self.foo = @"Bar";  // Setting an instance variable via a property accessor method.

The underscore is merely a matter of style, so that it's more clear that you're accessing the instance variable rather than the property.

Note that you can add a @synthesize statement yourself, and that will force the name of the corresponding instance variable to be whatever you want it to be. Likewise, if you add your own property accessor methods then that will prevent the instance variable from being generated automatically.

Darren
  • 25,520
  • 5
  • 61
  • 71
3

Xcode now auto-synthesizes all properties to be an instance variable called _propertyName. In many cases you no longer need @synthesize or to declare an instance variable explicitly.

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
2

With XCode 4.5 the default is now to add the underscore to the underlying instance variable. But the only impact this has for you is that you need to refer to that variable with the underscore. Here is an example:

@property (retain) UIColor color;

In your implementation code you can refer to the color like this:

[_color set]; // Now do some drawing...

For the outside world things remain unchanged.

object.color = [UIColor redColor];

This change is based on a common practice to name instance variables with an underscore prefix to distinguish them from local variables in your code.

aLevelOfIndirection
  • 3,522
  • 14
  • 18
  • You say the default - does that mean there is a way to turn it off? I'm pretty open-minded, but I also like consistency and this project has been around a while. I'd rather not have to change all of the other code in the project. I could just start doing it this way on my next project. – eattrig Sep 23 '12 at 06:01
  • Yes. The default means when XCode auto-synthesizes for you. You can always write @synthesize propertyName=propertyName and you will get the equivalent of what you had in older versions of XCode. – aLevelOfIndirection Sep 23 '12 at 06:07
  • So there's no way to tell Xcode to automatically generate the @synthesize like it used to? – eattrig Sep 23 '12 at 06:09
  • Before XCode did not auto-gerenate. But you can get the exact same behaviour as before if your write the synthesized line your self. I wrote above synthesize propertyName=propertyName but a simple @synthesize propertyName would have sufficed. – aLevelOfIndirection Sep 23 '12 at 06:14
0

Also, note that you normally want to access your property as [self.propertyName doSomething];, which is why auto-prefixing the instance variable with an underscore to indicate privacy makes sense.

If you really have to, you access it as [_propertyName doSomething] if you let it auto synthesize, but that bypasses the getter. Or, you can @synthesize propertyName = propertyName; to be able to use [propertyName doSomething] again, but why would you?

Vervious
  • 5,559
  • 3
  • 38
  • 57
-1

I have found that if you use an underscore before your @property name you are again able to implement your desired methods like before.

Josh G
  • 269
  • 1
  • 3
  • 3
  • If you do that then all other objects will see that underscore. So accessing that property from outside the object becomes object._propertyName, which is ugly. – aLevelOfIndirection Sep 23 '12 at 05:28
  • Sorry I should have said when you are trying to call your instance variable you add an underscore. – Josh G Sep 23 '12 at 05:33