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.
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
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.
Related
With the current version of Objective-C, what are the official standards and best practices for declaring ivars, using #property and #synthesize? There are a lot of posts and resources on the topic but most of them are fairly antiquated from a year or two ago. I recently learned to only declare ivars in a statement block in the implementation of a class so that the encapsulation principles of OOP aren't broken but is declaring ivars even necessary in this day and age? What would be a possible use case where doing:
#interface MyClass()
#property (nonatomic) NSString* data;
#end
#implementation MyClass{
#private
NSString* _data;
}
#end
is necessary? To further that, is it ever necessary to use #synthesize? My understanding is that using #property will auto-synthesize both the accessor methods as well as the backing ivars. I've done some experimentation and I noticed that when I don't declare NSString* _data', I can still access_data' in my class implementation. Does that mean that declaring ivars come down to a matter of style, up to the discretion of the programmer? Could I condense my code and remove all ivar declarations in the statement blocks in my implementation and just use #property in my private interface? If that's not the case, what are the advantages and disadvantages of explicitly declaring ivars?
Finally, #dynamic. From what I can gather, it's used to say to the compiler, "Hey compiler, don't auto-generate the accessor method and don't worry if you don't find an implementation for it, I'll provide one at runtime". Is that all #dynamic is used for or is there more to it?
I just want to clarify all these things because it seems like there's a lot of different opinions and that there's not necessarily one right answer. Plus as Objective-C grows and progresses, those answers will change so it'll be nice to have a concise and up-to-date guide. Thanks everyone!
(Also if there's anything that I could word better or make clearer, let me know)
EDIT:
In summary, what I'm asking is this:
1) Is declaring ivars with modern Objective-C necessary?
2) Can I achieve the same effects of declaring ivars and corresponding properties by just using #property?
3) What is #dynamic used for?
4) Can I completely forgo the use of #synthesize or is there a good use case for it?
Upvote and down vote as you see fit.
There's a lot to answer here. I'll break it down:
Declaring ivars
As you've correctly noted, modern versions of the compiler will synthesize backing instance variables for declared #properties. The exception to this is on 32-bit Macs, where the modern Objective-C runtime, including non-fragile instance variables, is not available. Assuming your application is not targeting 32-bit OS X, you don't need to explicitly declare the backing ivar for an #property.
If you still want to use an ivar directly, without a corresponding #property (something I consider a bad idea most of the time), you of course must still explicitly declare the ivar.
#dynamic
#dynamic is as you've said meant to tell the compiler "don't synthesize accessors for this property, I'll do it myself at runtime". It's not used all that often. One place it is used is in NSManagedObject subclasses, where if you declare a modeled property in the header, you don't want to compiler to complain that there's no implementation of accessors for that property, nor do you want it to generate accessors itself. NSManagedObject generates accessors for modeled properties at runtime. The story is similar for custom CALayer subclasses.
#synthesize
#synthesize explicitly tells the compiler to synthesize accessor methods, and (on iOS and 64-bit Mac) a corresponding ivar for the specified property. There are three main cases where you still need to use it:
32-bit Mac apps.
If you've written your own custom setter and getter (or just getter for readonly properties). In this case, the compiler won't synthesize accessors because it sees yours. However, it also won't synthesize the backing ivar. So, you must use #synthesize someProperty = _someProperty;, to tell the compiler to synthesize an ivar. It still won't synthesize accessor methods of course. Alternatively, you can explicitly declare a backing ivar. I favor using #synthesize in this case.
If you want to use a different name for the property's backing ivar than the default (property name with an added underscore prefix). This is rare. The main case I can think of for using it is when transitioning existing, older code, that includes direct ivar access and where the ivars are not underscore-prefixed.
Best current practice seems to be to use properties for all ivars placing the property either in the .h file if they are to be exposed and in the .m file in a class extension if local to the class.
No #synthesize is needed unless the ivar needs to be different than the underscore prepended property name.
Yes, #dynamic is as you describe.
Further, it is no longer necessary to declare local instance methods or order such that the method is above the use.
First off, #synthesize is gone for these scenarios: do not have to do it any more.
Secondly, you don't need the private ivar anymore either.
So in essence, you can just do properties.
The way of controlling access is the same idiom that had become popular before MOC dropped: put the property in the public interface as readonly and then make a readwrite version in the private interface (which should be, as you show above, merely the name with open and close parens).
Note also, that many of the things that cluttered up the public interface in the past can now ONLY be in the private interface, so for instance IBOutlets, etc., since the controller is going to be the only thing diddling them.
I never see #dynamic used anywhere except in CoreDate-generated entities.
For someone who first worked with C++ where the dream was always that the header/interface merely show the user of the class what they needed and all other details would be hidden, I think MOC (Modern Objective C) is a dream come true.
BTW, highly recommend the intro session from WWDC Modern Objective C (from 2012) and the one this year was great too.
I'm just wondering about semantics. When is something truly a "property" of an object? I noticed in a lot of Apple's APIs, they explicitly define getters and setters instead of using properties (e.g. URL and setURL on NSURLRequest/NSMutableURLRequest; surely the URL seems like a "property" of an URL request, right?) I'm wondering if there's some subtle thing that I'm missing or if Apple just doesn't like properties all that much. =P
UPDATE: As of iOS 8, Apple has converted most (if not all) of their non-property getters and setters to properties. (Probably done so that Swift compatibility would be easier.)
or if Apple just doesn't like properties all that much.
The real cause is that most of the Foundation framework (let's not forget you're talking about NS* classes) is old as dirt - they have been around there since the NeXT times... At that time, the Objective-C language didn't sport the #property keyword - to emulate properties, it was necessary for the programmers to declare and implement getter and setter methods manually, this applied to Apple's code as well.
Now the Foundation framework is so fundamental that it hasn't changed a lot. It hasn't been radically rewritten and as far as I'm concerned, programmers who wrote it didn't bother rewriting all the code using the new syntax. You can see that recently added classes do in fact feature declared properties instead of getters and setters, but that's not true for older classes.
Anyway, properties declared manually and those declared using #property and #synthesize are completely equivalent. That said, there's a very minor difference when accessing them, but that doesn't belong to the declaration thingy: if you write
someObject.someProperty
in your code, the someObject must have a complete and concrete type, so if a property named someProperty is nonexistent, you'll get a compiler error. In contrast,
[someObject someProperty]
and
[someObject setSomeProperty:]
allow you the method call even if it's undeclared.
Edit:
I ask what the semantic difference between them is
So by "semantic difference", you meant "when it should be used" rather than "does it run differently". I see. Well... Conceptually, properties represent state. A property is a particular characteristic of an object that may change over time. It's just an unrelated fact that properties are accessed using accessor methods in Objecive-C.
If you write a method that acts on the obejct (other than setting a property, of course), there's a fair chance you should be declaring and calling it as a method. If you access (read or write) an attribute of an object, that better fits the task of a property.
Having a getter and setter lets you use messages to access the item
[myObject someProperty] or [myObject setSomeProperty: someNewValue]
Making something a #property gives you the additionally ability to use dot notation to call the getter and setter. This is because #property chooses method names that make the class key-value-coding compliant for the particular value.
myObject.someProperty or myObject.someProperty = someNewValue
While it is possible to do this manually, it is considered best-practice to use #property when you want to use the dot notation. Over time, the behind-the-scenes bahaviours of #property and #synthesize have changed quite a bit particularly in regard to auto-creating storage for the associated pointer. Using #property makes it easier to keep up with Apple's changes in convention with little or no change in your code.
Additionaly, using #property makes your code much easier to read.
So in the guidelines it says:
For code that will run on iOS only, use of automatically synthesized instance variables is preferred.
When synthesizing the instance variable, use #synthesize var = var_; as this prevents accidentally calling var = blah; when self.var = blah; is intended.
// Header file
#interface Foo : NSObject
// A guy walks into a bar.
#property(nonatomic, copy) NSString *bar;
#end
// Implementation file
#interface Foo ()
#property(nonatomic, retain) NSArray *baz;
#end
#implementation Foo
#synthesize bar = bar_;
#synthesize baz = baz_;
#end
Question is, does this apply to public variables only or private too? It's not really clear on the documentation, but would like to have some thoughts or perspective on why "if" this is only for public or private only? I think that it just makes sense for all public/private so that you don't mess up ivars and using the property
I don't think it particularly matters whether the variables in question are public or private. The practice of synthesizing under a different name makes it explicit when you are accessing the variable directly instead of using the generated accessor method.
Perhaps there's a different question underlying what you're asking: should I typically access private ivars via the accessor or directly? I think most skilled iOS devs tend to use accessors unless there is some particular reason not to (performance, avoiding side effects like KVO, etc.). Doing so is more future-proof and allows for flexibility in the underlying implementation. In a very small way, you're coding to an interface rather than an implementation.
It also might be worth pointing out that the default behavior of Clang is going to change in the future so that property-backing ivars are synthesized named _foo by default. Clearly the powers-that-be consider consider underscoring ivars to be a best-practice.
I am pretty sure much of it comes down to personal preferences, so here are mine, for what they are worth:
I like to distinguish between public properties and "private" instance vars.
Properties are always accessed through their accessors, except for initialization (and within a manually created accessor method, for obvious reasons). Hence, the underscore in the backing ivar is useful, and not really an issue in my daily use of the properties.
Instance vars are used to hold state that is used internally in the methods, but not (directly) by other classes.
I have become very fond of declaring my instance variables in the .m file. Nice, clean and easy (no switching back and forth between .h and .m to declare ivars).
I find that this distinction helps me clear my mind and determine if a property is something outside agents should get and/or set directly (a property in .h), or if it is really just a help to get my method implementations to work (an ivar in .m).
I'd agree with Paul.s. that consistency is your friend, but to me, distinction is a friend, too.
I'm having a hard time understanding why I need to declare Instance Variables. Let me explain what I mean..
for example..
#interface LearningViewController : UIViewController {
UILabel *myText; // <--- Instance Variables
}
#property (nonatomic,retain) IBOutlet UILabel *myText;
-(IBAction)method:(id)sender;
#end
this can also be done as
#interface LearningViewController : UIViewController {
//instance variables go here, but are not declared, I just leave this field blank
}
#property (nonatomic,retain) IBOutlet UILabel *myText;
-(IBAction)method:(id)sender;
#end
as you can see.. in the latter example I ONLY built the setter / getter for the UILabel *myText
but in the former I declared the Instance Variables too.
Both end up working in the end
#implementation LearningViewController
#synthesize myText;
-(IBAction)method:(id)sender {
[myText setText:#"hey"];
//or
NSString *myObject = [[NSString alloc]initWithString:#"hey"];
[myText setText:myObject];
}
now both things produce the same result. So my question is, why? and what are the benefits of doing them either way?
And why would I build and object
NSString *myObject = [[NSString alloc]initWithString:#"hey"];
myText.text = myObject;
when I can just do
[myText setText:#"hey"];
thanks in advance.
Also, there are times when you want to use a protected or private iVar within a class and not make a property out of it. (for example, when you don't want to allow access of an iVar to anything but an instance of this class (private) or its descendants (protected). Properties declared in the header are available to any object that can "see" the target object. Automatically declaring ivars in the header as properties (with or without the declaration inside the curly braces) might be bad from the standpoint of information hiding.
You can also add an implementation section to your .m file: any properties you declare there will be private to the class. The benefit (obviously) is both in achieving information hiding where needed, and the ability to use the dot notation.
Originally Objective-C did not have properties and # synthesize did not exist. You had to declare your iVar (instance Variable) and write your own setters and getters.
When the language and runtime were revised to include properties and #synthesize, things were nicer. You no longer had to write your setters and getters. However you still had to declare your iVar.
Later still, the language and runtime evolved more and today, you don't even have to declare your iVar. (Although I tend to write #synthesize example = _example; so I can control what the generated iVar is named.)
This is a new feature and is only supported by relatively recent versions of the runtime. iOS versions less that 4.x are not supported, as are older versions of OSX.
If you are building software for today and the future, Go ahead and leave them out, If yot need legacy support, leave them in.
On the second part of the question, you are simply using the dot notation. You can set your myText.text equal to #"hey", the same way you are doing it in the second example.
[myText setText:#"hey"];
is synonymous to
myText.text = #"hey";
You don't need to declare an NSString to hold your value ahead of time.
You can leave iVars out, however I do not agree leaving out the iVars. The .h file in OOP is typically a header file that displays all variables and methods. It declares them. Assuming in the future you want to see what this class does, you just refer to the .h file. Or assuming someone else needs to look at that class, or use that class with his code to communicate with it. It makes it easier to look at the variables, see what is declared and what is not. That is, if you want to be programming professionally.
Now it really depends on what you want to do. The reason you would create an object is that so you are able to release it at a later time. So you continue to use it, and when you are done you just finish using it. Now creating instance variables for the whole class when they are just used in one method is not a good design decision. It is poor in a sense that the whole class is storing the variable, when in fact it is only used in one method. In this case, you should only create that object in that very method, and release it as soon as you're done with it.
Now sometimes doing
[myText setText#"hello"];
works. It really depends on your code. I guess the only way to really know the difference in situations is practice. Sometimes you need to set the label into another object, thus creating an object. Otherwise, it gets autoreleased etc...
Anyway, basically, use instance variables only for variables that are going to be used globally. And UI elements of course (since they are used by the whole class and interface builder).
Hope this helps.
As your code demonstrates, you don't technically need to declare instance variables, most of the time.
One critical exception to this is when you are compiling for the old (< 4.0) iOS runtime, as well as possibly the 32-bit Mac OS X runtime using GCC, which does not support the synthesis of instance variables.
Additionally, if you want to reserve space for later addition of instance variables (can be relevant if you are producing a framework and expect to extend a class at a later point), you'll need to explicitly declare the instance variables.
Edit: Long story short: Legacy, portability and extensibility concerns proscribe explicit ivars. For applications targeting 10.6, and especially 10.7, there is little or no need to declare them.
I have several years of experience in Obj-c and Cocoa, but am just now getting back into it and the advances of Obj-C 2.0 etc.
I'm trying to get my head around the modern runtime and declaring properties, etc. One thing that confuses me a bit is the ability in the modern runtime to have the iVars created implicitly. And of course this implies that in your code you should always be using self.property to access the value.
However, in init* and dealloc(assuming you're not using GC) methods we should be using the iVar directly (in the current runtime).
So questions are:
Should we use property accessors in init* and dealloc with Modern Runtime?
If so, why is this different? Is it just because the compiler can't see the iVar?
If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?
Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?
I read the docs several times, but they seemed a bit vague about all of this and I want to be sure that I understand it well in order to decide how I want to continue coding.
Hope that my questions are clear.
Quick summary of testing:
If you don't declare the ivar in legacy, compiler is completely unhappy
If you use #ifndef __OBJC2__ around ivar in legacy compiler is happy and you can use both ivar directly and as property
In modern runtime, you can leave the ivar undefined and access as property
In modern runtime, trying to access ivar directly without declaration gives error during compile
#private declaration of ivar, of course, allows direct access to ivar, in both legacy and modern
Doesn't really give a clean way to go forward right now does it?
In the current (OS X 10.5/GCC 4.0.1) compiler, you cannot directly access the runtime-synthesized ivars. Greg Parker, one of the OS X runtime engineers put it this way on the cocoa-dev list (March 12, 2009):
You can't in the current compiler. A
future compiler should fix that. Use
explicit #private ivars in the
meantime. An #private ivar should not
be considered part of the contract -
that's what #private means, enforced
by compiler warnings and linker
errors.
And why isn't there a way to
explicitly declare instance variables
in the .m file for the new runtime?
Three reasons: (1) there are some
non-trivial design details to work
out, (2) compiler-engineer-hours are
limited, and (3) #private ivars are
generally good enough.
So, for now you must use dot-notation to access properties, even in init and dealloc. This goes against the best practice of using ivars directly in these cases, but there's no way around it. I find that the ease of using runtime-synthesized ivars (and the performance benefits) outweigh this in most cases. Where you do need to access the ivar directly, you can use a #private ivar as Greg Parker suggests (there's nothing that prevents you from mixing explicitly declared and runtime-synthesized ivars).
Update With OS X 10.6, the 64-bit runtime does allow direct access to the synthesized ivars via self->ivar.
Since instance variables themselves can only be synthesized in the modern runtime (and must be declared in the #interface under 32-bit or pre-Leopard), it's safest / most portable to also declare the ivar
Should we use property accessors in init* and dealloc with Modern Runtime?
My rule of thumb is "possibly" for -init*, and "usually not" for -dealloc.
When initializing an object, you want to make sure to properly copy/retain values for ivars. Unless the property's setter has some side effect that makes it inappropriate for initialization, definitely reuse the abstraction the property provides.
When deallocating an object, you want to release any ivar objects, but not store new ones. An easy way to do this is to set the property to nil (myObject.myIvar = nil), which basically calls [myObject setMyIvar:nil]. Since messages to nil are ignored, there is no danger in this. However, it's overkill when [myIvar release]; is usually all you need. In general, don't use the property (or directly, the setter) in situations where deallocation should behave differently than setting the variable.
I can understand eJames' argument against using property accessors in init/dealloc at all, but the flipside is that if you change the property behavior (for example, change from retain to copy, or just assign without retaining) and don't use it in init, or vice versa, the behavior can get out of sync too. If initializing and modifying an ivar should act the same, use the property accessor for both.
If so, why is this different? Is it just because the compiler can't see the ivar?
The modern runtime deals with class size and layout more intelligently, which is why you can change the layout of ivars without having to recompile subclasses. It is also able to infer the name and type of the ivar you want from the name and type of the corresponding property. The Objective-C 2.0 Runtime Programming Guide has more info, but again, I don't know how deeply the details explained there.
If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?
I haven't tested this, but I believe you're allowed to access the named ivar in code, since it actually does have to be created. I'm not sure whether the compiler will complain, but I would guess that since it will let you synthesize the ivar without complaining, it is also smart enough to know about the synthesized ivar and let you refer to it by name.
Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?
You should be able to access the property and/or ivar anytime after the instance has been allocated.
There is another SO question with similar information, but it isn't quite a duplicate.
The bottom line, from the Objective-C 2.0 documentation, and quoted from Mark Bessey's answer is as follows:
There are differences in the behavior that depend on the runtime (see also “Runtime Differences”):
For the legacy runtimes, instance variables must already be declared in the #interface block. If an instance variable of the same name and compatible type as the property exists, it is used—otherwise, you get a compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.
My understanding is as follows:
You should not use property accessors in init* and dealloc methods, for the same reasons that you should not use them in the legacy runtime: It leaves you open to potential errors if you later override the property methods, and end up doing something that shouldn't be done in init* or dealloc.
You should be able to both synthesize the ivar and override the property methods as follows:
#interface SomeClass
{
}
#property (assign) int someProperty;
#end
#implementation SomeClass
#synthesize someProperty; // this will synthesize the ivar
- (int)someProperty { NSLog(#"getter"); return someProperty; }
- (void)setSomeProperty:(int)newValue
{
NSLog(#"setter");
someProperty = newValue;
}
#end
Which leads me to think that you would be able to access the synthesized ivar in your init* and dealloc methods as well. The only gotcha I could think of is that the #synthesize line may have to come before the definitions of your init* and dealloc methods in the source file.
In the end, since having the ivars declared in the interface still works, that is still your safest bet.
I am running into the same problem. The way I am working around not being able to access the synthesized instance variables is the following:
public header
#interface MyObject:NSObject {
}
#property (retain) id instanceVar;
#property (retain) id customizedVar;
#end
private header / implementation
#interface MyObject()
#property (retain) id storedCustomizedVar;
#end
#implementation MyObject
#synthesize instanceVar, storedCustomizedVar;
#dynamic customizedVar;
- customizedVar {
if(!self.storedCustomizedVar) {
id newCustomizedVar;
//... do something
self.storedCustomizedVar= newCustomizedVar;
}
return self.storedCustomizedVar;
}
- (void) setCustomizedVar:aVar {
self.storedCustomizedVar=aVar;
}
#end
It's not that elegant, but at least it keeps my public header file clean.
If you use KVO you need to define customizedVar as dependent key of storedCustomizedVar.
I'm relatively new to Obj-C (but not to programming) and have also been confused by this topic.
The aspect that worries me is that it seems to be relatively easy to inadvertently use the iVar instead of the property. For example writing:
myProp = someObject;
instead of
self.myProp = someObject;
Admittedly this is "user" error, but it's still seems quite easy to do accidentally in some code, and for a retained or atomic property it could presumably lead to problems.
Ideally I'd prefer to be able to get the runtime to apply some pattern to the property name when generating any iVar. E.g. always prefix them with "_".
In practice at the moment I'm doing this manually - explicitly declaring my ivars, and deliberately giving them different names from the properties. I use an old-style 'm' prefix, so if my property is "myProp", my iVar will be "mMyProp". Then I use #synthesize myProp = mMyProp to associate the two.
This is a bit clumsy I admit, and a bit of extra typing, but it seems worth it to me to be able to disambiguate a little bit more clearly in the code. Of course I can still get it wrong and type mMyProp = someObject, but I'm hoping that the 'm' prefix will alert me to my error.
It would feel much nicer if I could just declare the property and let the compiler/runtime do the rest, but when I have lots of code my gut instinct tells me that I'll make mistakes that way if I still have to follow manual rules for init/dealloc.
Of course there are also plenty of other things I can also do wrong...