When using Objective-C properties can you stop creating instance variables altogether or do explicit instance variables (not the ones synthesized by the properties) still serve a purpose where properties would be inappropriate?
can you stop creating instance variables altogether
No, you can't (in a sense). What you can do is stop declaring them if you have properties. If you synthesize a property and you haven't declared the instvar, it will get declared for you, so you are creating an instance variable, just not explicitly.
do they still serve a purpose where properties would be inappropriate?
It used to be the advice to create properties for everything because having synthesized properties does almost all of the retains and releases for you. However, with ARC that reason for using properties to wrap the memory management has gone away. The advice now (for ARC) is, I believe, use properties to declare your external interface, but use direct instance variables where the variable is part of the object's internal state.
That's a good reason to adopt ARC: properties revert to their true purpose only of being part of the class's API and it's no longer necessary to use them as a hacky way to hide memory management work.
Edit
One more thing: you can now declare instance variables in the #implementation so there is now no need to leak any implementation details in the #interface. i.e.
#implementation MyClass
{
NSString* myString;
}
// method definitions
#end
And I'm pretty sure it works in categories too. - see comment below
I recommend declaring everything as properties and avoiding manual ivars altogether. There is no real upside to manually creating ivars. Declare public properties in your header #interface, declare private properties in a private class extension in your .m file.
To some of JeremyP's points, internal use of accessors still has significant value under ARC, even though memory management is no longer a significant concern. It ensures that KVO works properly, subclasses better, supports custom setters (particularly for things like NSTimer), supports custom getters (such as for lazy instantiation), etc. It is exceedingly error-prone to have a mix of accessors and ivars. It's far too easy to forget which you need to access in which way. Consistency is the hallmark of good ObjC.
If you absolutely must declare an ivar for some reason, then you should do it in the #implementation block as JeremyP notes.
UPDATE (Oct-2013):
Apple's guidance (From Programming with Objective-C: Encapsulating Data):
Most Properties Are Backed by Instance Variables
In general, you should use accessor methods or dot syntax for property access even if you’re accessing an object’s properties from within its own implementation, in which case you should use self:
...
The exception to this rule is when writing initialization, deallocation or custom accessor methods, as described later in this section.
This question was addressed before here
When you use synthesize the instance variables are handled and instantiated for you. If you're using Lion with the new version of XCode also take a look at the various properties in ARC in Transitioning to ARC
you can always access properties from outside. So if you want a variable only to be read from inside a class you still have to declare a iVar. Also accessing a public ivar with object->ivar is slightly faster than using a method-call.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?
Note: For the folks digging around trying to understand this, I figured-out the source of my confusion. In the .h, I had:
...
#interface myClass : parentClass {
className *variableName:
}
#property (strong, nonatomic) className *variableName;
...
This leads to self.variableName and _variableName being two distinct variables in the .m. What I needed was:
...
#interface myClass : parentClass {
className *_variableName:
}
#property (strong, nonatomic) className *variableName;
...
Then, in the class' .m, self.variableName and _variableName are equivalent
In brand-new, Xcode 4.5+, with ARC, targeting iOS 5.0+ project, is there a distinct advantage (runtime efficiency, speed, etc.) to using _variableName over self.variableName vs. the old-style #synthesize variableName?
My understanding is that Xcode 4.5+ will create a default accessor _variableName that is equivalent to self.variableName and the only reasons not to use #synthesize variableName is to avoid confusion between iVars and passed-in variables, correct?
To me, just using self.variableName to access an iVar seems the most straightforward and clear as to which variable you're looking for. Other than typing _ vs. self., is there an advantage to using _variableName?
My understanding is that Xcode 4.5+ will create a default accessor "_variableName" that is equivalent to self.variableName and the only reasons not to use "#synthesize variableName" is to avoid confusion between iVars and passed-in variables, correct?
In this case, _variableName isn't the accessor, it's an ivar that is automatically generated by the compiler and used in the automatically #synthesized setters and getters. Generally, it is considered best to use accessors whenever possible (i.e. self.variableName) so that things like key-value observation and bindings work for that property.
When you access an ivar directly, it is accessed via direct memory access, the same way you would access data in a struct. It simply takes the pointer for the object that owns the ivar, offsets the memory address and attempts to read or write to the memory at that location. Using dot notation (self.variableName) calls the accessor methods to set or get that property and can do a number of different things along the way, such as:
1) Locking: If the property is going to be used in multiple threads and is an atomic property, the runtime will automatically do some locking to make sure that the property is not accessed at the same time from multiple threads. If your object is not meant to be used on multiple threads, you can give the nonatomic hint in your property declaration so that the synthesized accessors skip the locking.
2) Key-Value Notifications: The default setters for properties call -willChangeValueForKey: and -didChangeValueForKey:, which sends out notifications when the property is changed. This is necessary for anything to update properly if bindings are used, and for any other key-value observation.
3) Custom accessor behavior: If you end up writing your own setters and getters, any custom stuff that you implement within those.
Technically, accessing the ivar directly is faster than using accessors, but there are very few situations in which it will make a significant performance difference, and would probably be a case of premature optimization. Even if you don't feel like you would be using the benefits listed above right away, it's probably better to use the accessors anyway so that if you decide later on you need some of that functionality, you don't have to change every instance of accessing that variable (and possibly be creating unexpected new bugs in the process).
In addition, if you are accessing ivars directly and end up refactoring your class into categories or subclasses, it gets messy because you usually have to declare the ivar as a #protected variable. You wouldn't have to do this if you are using the accessors.
Generally, I try to only access the ivars directly in init, dealloc, and the property's accessor. A lot of engineers go by this rule of thumb because sometimes the custom stuff that happens in accessors can cause unexpected behavior while the object is init'ing or dealloc'ing. For example, if anything in the accessors causes something to retain or release your object or even form a zeroing weak reference to it, it will cause a crash if used in dealloc.
In the latest Xcode #synthesize is optional. By default, omitting #synthesize is the same as writing
#synthesize someName = _someName;
The only reason to use #synthesize is to rename the instance variable created to store the value of the property, for example
#synthesize someName = someSpecialName;
When you use self.variableName to access a variable, you go through a property, which is a short method that accesses the instance variable for you. Although the method dispatch is very fast, it may perform additional services for you, such as synchronizing the access to the variable (this is the case when you specify atomic or do not specify nonatomic in the property declaration). In cases like that, the access through self.variableName will be somewhat slower. If done in a tight loop, this could potentially make a difference. That is why you sometimes want to access the underlying instance variable directly by using _variableName.
I was wondering what exactly are the differences between using the (get) accessor for reading the value of property and directly using the iVar?
Say I have a class which declares a property:
#interface Foo : NSObject
#property (strong) NSString *someString;
#end
And in the implementation I'm using it. Are there any differences between the following two lines:
someLabel.text = self.someString;
someLabel.text = _someString;
For set accessors it's clear. Afaik for strong properties the accessor takes care of retain and release (an interesting 'side question' would be if ARC changes that, i.e. does setting the iVar directly [assuming it's not an __weak iVar] also retain and release correctly using ARC), also KVO requires the use of accessors to work properly etc. But what about getters?
And if there's no difference, is there one way considered best practice?
Thx
As you know, calling self.someString is really [self someString]. If you chose to create a property then you should use the property. There may be other semantics added to the property. Perhaps the property is lazy loaded. Perhaps the property doesn't use an ivar. Perhaps there is some other needed side effect to calling the property's getter. Maybe there isn't now but maybe this changes in the future. Calling the property now makes your code a little more future proof.
If you have an ivar and a property, use the property unless you have explicit reason to use the ivar instead. There may be a case where you don't want any of the extra semantics or side effect of the property to be performed. So in such a case, using the ivar directly is better.
But ultimately, it's your code, your property, your ivar. You know why you added a property. You know any potential benefits of that property, if any.
I think this what you are looking for. Why use getters and setters?
There are actually many good reasons to consider using accessors rather than directly exposing fields of a class - beyond just the argument of encapsulation and making future changes easier.
Here are the some of the reasons I am aware of:
Encapsulation of behavior associated with getting or setting the
property - this allows additional functionality (like validation) to
be added more easily later.
Hiding the internal representation of the
property while exposing a property using an alternative
representation.
Insulating your public interface from change -
allowing the public interface to remain constant while the
implementation changes without effecting existing consumers.
Controlling the lifetime and memory management (disposal) semantics
of the property - particularly important in non-managed memory
environments (like C++ or Objective-C).
Providing a debugging
interception point for when a property changes at runtime - debugging
when and where a property changed to a particular value can be quite
difficult without this in some languages.
Improved interoperability
with libraries that are designed to operate against property
getter/setters - Mocking, Serialization, and WPF come to mind.
Allowing inheritors to change the semantics of how the property
behaves and is exposed by overriding the getter/setter methods.
Allowing the getter/setter to be passed around as lambda expressions
rather than values.
Getters and setters can allow different access
levels - for example the get may be public, but the set could be
protected.
I am not a very experienced person to answer this question, even though I am trying to give my views and my experience by seeing source code which is around 10yrs older.
In earlier codes they were creating ivars and property/synthesise. Nowadays only property/synthesise is used.One benefit I see is of less code and no confusion.
Confusion!!! Yes, if ivars and its property are of different name, it does create a confusion to other person or even to you if you are reading your own code after a while. So use one name for ivar and property.
By using property KVO/KVB/KVC are handled automatically, thats for sure.
#property/#synthesise sets your ivar to 0/nil etc.
Also helpful if your subclass contains same ivar.
For mutable objects Dont make properties.
I'm in the process of looking over some code in a large project, and I have noticed that in several of the classes, instance variables are created but no corresponding properties (#property) are created.
Is it "wrong" to create instance variables without properties? Doesn't this become a memory management issue?
I've actually never seen code like this before so I'm not sure what to think at this point.
Thanks in advance!
#properties are merely shorthand -- very convenient short-hand -- for code you can write yourself, no magic about it.
It may also be that the #properties are declared in the implementation file within a class extension and there is no publicly accessible API for directly manipulating the instance variables.
There's no reason that you have to use the Objective-C 2 style setters/getters to manage your instance variables - as long as the instance variable is released within the dealloc method (if indeed it's a alloced/inited object, etc.) then there's nothing to worry about.
Bear in mind that prior to Objective-C, such properties (and the whole #property/#synthesize syntax) simply didn't exist, so you had to create your own getters/setters if you deemed it necessary/convenient.
Not at all. Instance variables work fine, and are subject to the same memory management rules as anything else: retain it before saving it to the instance var, and make sure you release it when you don't need it anymore (typically in the dealloc).
Some history here might be helpful:
In the beginning, there were only instance variables. "Properties" existed only in an informal way, by convention, for objects outside your class to access "public" data that the class exposed. You'd write your own -(Foo *)foo and -(void)setFoo:(Foo *)f methods for each of these. Those often were like boilerplate code, trivially returning the ivar in the first case, and doing the right retain/release/set dance in the latter.
So Objective-C 2.0 came along and gave us the ability to declare properties with the language syntax, and even generate the accessors for us-- lots of time and boilerplate code was saved.
As time went on, some people began to think about all ivars as "properties", public or private. The public ones appear in the .h file as #properties, but you can also create a private interface to your object in the .m file that declare your "private" #properties, so you can use the accessors inside your class. This might or might not be overkill, depending on your philosophy to it, but this I think has to the situation you see now, where naked ivars look suspicious.
They shouldn't. Instance variables happily exist without any of the other machinery. Just get your retain/release right (in non-GC runtimes).
As you get more advanced, see #bbum's answer to this question:
Must every ivar be a property?
for some more varsity things to think about around the benefits of properties around KVO and subclassing.
Properties for instance variables aren't mandatory. In fact, prior to v2.0 of Objective-C, there was no such thing as properties -- you had to write your own accessors and mutators for instance variables (if you wanted to access them outside of the class). Properties can simplify memory management, but to be honest, memory management of ivars isn't that difficult, and it's not hard to handle yourself.
I see it recommended all over the place when coding for iOS that properties should be used for accessing instance variables because of the benefits this lends to memory management, among other things.
This advice doesn't sit terribly well with me. I find that using properties instead of plain old ivars just takes too much code and I don't really see the benefits if you're comfortable with memory management. Is it really that important? What's your approach to managing instance variables?
It's not really necessary to declare properties for all ivars. A few points come to mind:
If an ivar is only going to be assigned to once during the lifetime of the object, you don't really gain anything by declaring a property. Just retain/copy/assign during init and then release as necessary during dealloc.
If an ivar is going to be changed frequently, declaring a property and always using the accessors will make it easier to avoid memory management errors.
You can declare properties in a class extension in the .m file rather than the .h file if the properties and ivars are meant to be private.
When targeting iOS 4.0+, you don't need to declare ivars at all in your header if you define a property and synthesize accessors.
So I generally use properties, but for things like a NSMutableArray that an object allocates during init and uses to hold a bunch of whatevers, I'll use a plain old ivar since I'll never be reassigning the ivar.
While Daniel's answer is correct, I think it misses an important point. Namely:
I find that using properties instead
of plain old ivars just takes too much
code and I don't really see the
benefits if you're comfortable with
memory management.
The benefits are consistency; consistent memory management and consistent behavior.
Notably, these two lines of code can actually have extremely different behavior at runtime:
iVar = [foo retain];
self.iVar = foo;
The first is a direct setting of the instance variable and there will be no change notifications. The second goes through the setter and, thus, preserves any subclass customizations upon set and ensures that any observers of the property are notified of the change.
If you are using ivars directly throughout your code (internally to the class -- if you are using ivars of an instance directly from outside that instance, well... any contractor working on your codebase should double their rates ;), then you must either also handle change notification propagation manually (typically by calling willChangeValueForKey:/didChangeValueForKey) or explicitly engineer your application to avoid use of mechanisms that rely upon Key-Value Observation.
You say "takes too much code". I don't see that; in the above two lines of code, the dot syntax is fewer characters. Even calling the setter method using traditional syntax would be less code.
And do not discount the value in centralizing memory management; one accidental omission in a myriad of call sites and crash city.
Property are just syntax sugar that avoid you to write same methods over and over.
With a property you have a setter that release the old object and retain the new one for free.
For the private fields - I suggest it is safe to use direct ivars only for primitive types (BOOL/int/float etc). I find a good practice wrapping everything related to memory-management in properties - even rarely-used fields. Additional bonus of this approach is that IDE usually highlights direct ivars access differently, so you always have a nice separation of simple scalar fields and object-type fields.
Contrary to this I would strongly discourage any direct ivars in the class public interface. Because of the dynamic nature of language it can lead to runtime errors that are extremely hard to find, localize and fix. Consider the following hierarchy
#interface BaseControl
...
#end
#interface Label : BaseControl
...
#end
#interface Button : BaseControl {
#public
BOOL enabled;
}
#end
and a code snippet
- (void)enableAllButtons {
NSArray *buttons = [self getAllButtons]; // expected to contain only Button instances
for (Button *button in buttons) {
button->enabled = YES;
}
}
Now imagine there's an error somewhere in -getAllButtons logic and you also get some Label's returned in that array - so those Label class instances will get missing ivar assigned. The fact that may be surprising is that -enableAllButtons will not crash in that case. But at that point those Label instances internal structure is corrupted and this will cause undefined behavior and crashes when they are used elsewhere.
Like some popular problems with memory management (and in general - with dangling pointers) - this kind of problems is hard to find and localize - because the appearance of the error usually is distant (in terms of time, code or app flow) from the place, causing the error. But with that particular problem you even don't have handy tools (like leak/zombies analyzers etc.) to help you localize and fix it - even when you learn how to reproduce it and can easily investigate erroneous state.
Obviously if you use #property (assign) BOOL enabled; you'll get an easy-to diagnose and fix runtime exception in -enableAllButtons.
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...