-1

Say this is in my header file:

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (weak) IBOutlet NSSlider *slider;
- (void)doSomething;

@end

…and this is the *m:

@implementation AppDelegate

- (void) doSomething {[self.slider setFloatValue:0];}

@end

I'm new to Xcode and Objective C, and I would like to use and understand the modern “tools” presented by Apple in its documentation, namely ARC, or here more specifically the ability to skip @synthesize.

If I understood correctly, @property (weak) IBOutlet NSSlider *slider; does a few things for me, including:

  • creating an instance variable called _slider;
  • creating a getter named slider;
  • creating a setter named setSlider.

I've been doing C++ until now, so I see instance variables as the equivalent of what I am calling (rightly, I hope) members of my C++ classes, which I incidentally always call _member.

I understand that the whole point of encapsulation is that, if you're outside a given class, you have to use accessors to access those variables; they are private to you, so there's no way you can access them via _member even if you tried.

But, when I'm writing my *.m file of my class, _member means something. Back to my example, I think self.slider and _slider are equivalent. The latter comes naturally to mind first, as it saves a few character.

My question is: are the two absolutely equivalent?

I know this looks similar to this question, for example, but here’s a few reasons why I wanted to ask myself:

  • I don’t use @synthesize, so I’m really not the one creating _slider, and I wonder if this makes a difference (I believe this is a fairly recent improvement of ObjC, and most answers still refer to @synthesize);
  • it seems that on average, most conversations end up with “so, just use self.name”, but I don’t grasp if this is just a recommendation, a convention, of something more important (with an impact on, say, the performance);
  • similarly, some say you should only use _name in methods like dealloc and its friends; but I don’t write those thanks to ARC, so does this mean I should never use _name? If so, why?

I hope this justifies this post, I apologies if I missed a preexisting answer. Thanks in advance for your help.

Community
  • 1
  • 1
  • This statement is incorrect, "I understand that the whole point of encapsulation is that, if you're outside a given class, you have to use accessors to access those variables; they are private to you, so there's no way you can access them via _member even if you tried." you can use the arrow operator to access the variable, e.g. `self->_slider`. By the way, I'm not suggesting you use it though. – lucianomarisi May 29 '14 at 19:54
  • Similar question: [Use property in class extension instead of ivar in post ARC](http://stackoverflow.com/questions/23850141/use-property-in-class-extension-instead-of-ivar-in-post-arc). – Martin R May 29 '14 at 19:55
  • 1
    This has been covered exhaustively on Stack Overflow already. Search for "[objective-c] property vs ivar" or "[objective-c] property vs instance variable". – Rob May 29 '14 at 20:11
  • @lucianomarisi I think I'm missing something here… If I try something like `MyObject->_name` outside the implementation of the class `MyClass` for this object, Xcode tells me “‘MyClass’ does not have a member named _name”. Doesn't that translate the fact that, outside the implementation, you can only access this member via the property `MyObject.name`(or `[MyObject name]`)? –  May 29 '14 at 20:12
  • 1
    Thanks @MartinR and @Rob; I guess I didn't use the right keywords, I'm sorry. –  May 29 '14 at 20:13
  • @aurelienche That technique of dereferencing ivars is, as lucianomarisi implied, frowned upon nowadays. You'd be well advised to stick with properties for a litany of reasons (discussed extensively elsewhere). Good luck! – Rob May 29 '14 at 20:15
  • @ aurelienche the reason you don't see it is because you would need to declare the instance variable in the header using @public. Have a read at this question http://stackoverflow.com/questions/5784875/does-a-private-property-create-an-private-instance-variable – lucianomarisi May 29 '14 at 20:58
  • @lucianomarisi Thank you, that clears things up! –  May 29 '14 at 21:03

2 Answers2

2

self.name = compiles to [self setName:] this is very different then setting the variable directly.

One of the main reasons that using the default setter differs deals with key value observing often referred to as KVO. Using the setter will notify observers of changes, setting the _name directly will not.

Thats not to say you can't fire the events your self with willChangeValueForKey: and didChangeValueForKey:, but the default implementation will handle that for you. So as you say outside the class accessing them you have to use the property get/set but inside your class setting the variable directly will lose out on some notifications. I'm sure there are other differences this is the first that comes to mind.

Using the variable directly does have it's use cases, such as a custom property setter. I think the main take away is the dot syntax is a hidden function call to get/set.

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOCompliance.html

utahwithak
  • 6,235
  • 2
  • 40
  • 62
0

Under basic circumstances, where you use the pre-made accessors, you could probably get away with using _slider or self.slider within your class interchangeably. They're not equivalent in how they compile necessarily, but the functionality could be said to be equivalent.

The bigger issue comes into play when you start overriding those accessors. When those accessors do more than just "getting" or "setting" a variable, such as accessing some sort dependency variable, accessing the instance variable directly bypasses that functionality that the accessors provide. In these cases, I don't think it can be said that the two are equivalent at all.