When to use self on class properties? - objective-c

When is self needed for class properties? For example:
self.MyProperty = #"hi there";
vs
MyProperty = #"hi there";
MyProperty is an NSString set as (nonatomic, copy). Is there any difference in memory management for the above two?
What about when there is no property and the variable MyProperty is declared in the header file? Is a property needed if it is never referenced outside of the class? Does it make a difference to memory management?

Yes, there is a difference for both memory and performance.
MyProperty = #"hi there";
This is considered a direct assignment. There is practically no memory or performance impact. Of course, that's not to say it's best practice - that's a different question :)
#property(nonatomic, copy) NSString *MyProperty;
// ...
self.MyProperty = #"hi there";
This statement has a significant impact on memory and performance. This is essentially equivalent to:
-(void)setMyProperty(NSString *)newValue {
if (MyProperty != newValue) {
[MyProperty release];
MyProperty = [newValue copy];
}
}
The old value is released and the new value is copied into MyProperty. This is acceptable and especially typical when dealing with strings when the string your assigning is mutable (ie, it could change later).
If, as in your example, you're simply assigning a static string (#"hi there"), there is nothing wrong with directly assigning the string value; it's more efficient however the difference in performance is trivial.
You can declare a property with #property as retain, copy, or assign (default is assign). You can then generate "accessor" (getter/setter) methods by using #synthesize. Here is what the setter methods look like that are generated when you do so:
// #property(nonatomic, assign)
-(void)setMyProperty(NSString *)newValue {
MyProperty = newValue;
}
// #property(nonatomic, retain)
-(void)setMyProperty(NSString *)newValue {
if (property != newValue) {
[property release];
property = [newValue retain];
}
// #property(nonatomic, copy)
-(void)setMyProperty(NSString *)newValue {
if (property != newValue) {
[property release];
property = [newValue copy];
}
}
More information on ObjectiveC Declared Properties.
"You can use the #synthesize and #dynamic directives in #implementation blocks to trigger specific compiler actions. Note that neither is required for any given #property declaration.
Important: If you do not specify either #synthesize or #dynamic for a particular property, you must provide a getter and setter (or just a getter in the case of a readonly property) method implementation for that property."
In other words, if you declare a property but don't synthesize the property, you won't be able to use [self MyProperty] or self.MyProperty unless you define 'MyProperty' and 'setMyProperty' methods. If you don't declare a property then you simply have an instance variable.
Note: #dynamic doesn't generate the accessors. It's really used if you're dynamically (ie, magically) resolving accessor methods via loading code or dynamic method resolution.

The difference is that
self.MyProperty = #"hi there"
is dot-notation call that will call the generated accessor, which will handle the retain counts correctly (equivalent to [self setMyProperty:#"hi there"]), whereas
MyProperty = #"hi there"
is a direct assignment to your member variable, which doesn't release the old value, retain the new one, or do anything else your accessor does (e.g., if you have a custom setter that does extra work).
So yes, there is a big difference in memory management and in behavior in general between the two. The latter form is almost always wrong, unless you know specifically why you are doing it and that you are handling the retain counts correctly yourself.

If you use automatic Key-Value Observing (or any Cocoa technology that builds on it - like bindings, ...), it is also important use the setter. The observer would not receive any notification if you assign to the ivar.
If you bind "MyProperty" to a NSTextfield and you change your "MyProperty" ivar via code, the bound textfield would still display the old value as it did not receive any change notification.

To access a variable, there is often no need to use the dot notation. Thus, in code generated by the XCode templates, you will see things like:
[flipsideViewController viewWillAppear:YES];
There is no need to write self.flipsideViewController here, because the accessor method typically does nothing except handing you the variable.
So a good rule of thumb is to use dot notation when you are setting a variable (absolutely necessary unless you want to do your own retaining and releasing), but not when you're accessing it:
self.aString = #"Text text text";
NSLog (aString); // No need for self.aString here
NSString* tmpString = aString; // Here neither
When you're using non-object types, like int or float or many others, you can get away with not using the dot notation/setter method. In these cases, there is nothing to retain, so the setter method will do little apart from just assigning the value.
However, synthesized getters and setters do more than just retaining and releasing. As others have mentioned, they are also the engine that keeps the KVO system running. Thus, you should use the proper setters even on ints, floats and the rest.
What about the accessors then? In more advanced contexts, a class might respond to a request for a variable's value even when the variable doesn't exist. To quote the exalted Objective-C manual, classes might provide "method implementations directly or at runtime using other mechanisms [than simple accessor methods] such as dynamic loading of code or dynamic method resolution."
(One way of implementing this sort of on-the-fly response to messages is by overriding NSObject methods like methodSignatureForSelector: and forwardInvocation: .)
For this reason, using properly declared interfaces (whether synthesized or not) is always a good idea when you're working on something big. But it's completely ok to access ivars directly, as long as you set them using the proper API.
(Note: I'm not a Cocoa guru, so corrections are more than welcome.)

For the second part of the question, property definition is not needed, it is a help to us . The #synthesize directive on property generates accessor methods for properties so we don't have to do it manually, and because:
This code instructs the compiler to
generate, or synthesize, the accessor
methods. The compiler will generate
the accessor methods using
well-tested, fast algorithms that are
ready for multi-core and
multi-threaded environments, including
locking variables in setter methods.
Not only does using properties reduce
the amount of code that you have to
write, it replaces that code with the
best possible accessors for today's
modern multi-core systems. Later, if
you need to provide an alternative
implementation for a property
accessor, you can simply add the
appropriate code to your class.
http://developer.apple.com/leopard/overview/objectivec2.html
The nonatomic will avoid use of locking when accessing variables, if you don't specify anything then default is atomic. Locking is useful on multithreaded systems. The copy specifies what code should be generated for accessors, copy will copy the object, retain will retain new object and release old one, assign is good for simple variables like int to just plain assign values.
So when you define your property as you did above (nonatomic,copy) and then use self.MyProperty = #"Hey" you're actually calling generated accessor that will make a copy of the new variable as opposed to just assigning it. You can override accessor and add checking to it.
Because of the above I would say that defining property has benefits even when the variable is not used outside of the class.
I believe to access properties you should use self.MyProperty instead of just MyProperty but I can't point you to explanation why.
Might be something to do with the fact that compiler will generate from
self.MyProperty = #"Hey";
this:
[self setMyProperty: #"Hey"];
But I'm only speculating here.
Whether you call self.MyProperty or MyProperty it should not affect memory management (I would still prefer the first - self.MyProperty).
See Objective-C 2.0 Overview for some high level description from Apple.

As a supplement to the other answers, try to think of it this way:
self.MyProperty = #"hi there";
or
[self setMyProperty:#"hi there"];
(which are equivalent) both call a method, whereas
MyProperty = #"hi there";
Simply sets a variable.

This is an old question, though it used to be "When do I write [self setMyProperty:#"hi there"]?" (Note that self.MyProperty = #"hi there" is exactly equivalent to this.)
The answer I've always heard (and which makes good sense) is always use the accessor; never write MyProperty = #"hi there". There are several reasons:
Memory management is handled for you; you don't have to worry about proper retaining/releasing/copying.
It's easier to modify your code in the future; if at some point you realize that changing MyProperty needs to have a particular side effect, you can add to the setter method without finding every time you set MyProperty.
If you ever have problems with MyProperty, it's easy to add logging code to the setter (or even getter) to find out every time it's changed (or even accessed).
Summary: it's safest and most flexible to always use [self setMyProperty:#"hi there"] or self.MyProperty = #"hi there", and never use MyProperty = #"hi there".

Still not clear on when to use the accessors and when to do direct assignment on ivars ? I have seen lot of Apple examples which directly access the ivars. So using properties for all ivars seems pedantic overkill.
It seems only significant ivars which need to be around longer and are accessed outside tend to use the properties.
Would appreciate some Cocoa gurus to step in and clarify.

Related

Objective-C/ARC ivar vs property [duplicate]

This question already has answers here:
Property vs. ivar in times of ARC
(2 answers)
Closed 8 years ago.
I've been up and down the Google and the Stack and read many articles if not outright debates over ivars and properties. But still, even after all this reading I remain confused.
I understand ivar's are private and properties are typically used to expose (well) class properties. But I understand properties to be more than that, they contain Getters and Setters and when it comes to memory management (even under ARC) I can see the benefit to using them exclusively.
But my question is; does any of this matter anymore now that we have ARC? (see comment in example code below).
Consider:
#interface MyClass
#property(strong) NSMutableArray *myArray;
#end
#interface MyClass
-(instancetype)init {
if (self = [super init]) {
self.myArray = [NSMutableArray array];
// OR
// Will this NOT call the Setter? Hence, leading
// to possible memory leak issues?
_myArray = [NSMutableArray array];
}
return self;
}
#end
self.myArray = [NSMutableArray array]; is considered bad form in init. You should avoid the use of setters entirely in your initialisation. The risk is that a subclass may override the method, in which case you're calling a method on a class that hasn't been inited yet (because it's got only as far as initing you). See the obligatory Mike Ash citation.
_myArray = ... does not call the setter and is therefore the correct form for an init regardless of whether you also have a property.
ARC makes correct memory-management all but a none issue. The debate is exclusively what you want technically to expose and how adaptable you want your internal code to be. I tend to prefer explicit instance variables because that shouts 'private implementation detail'.
Back in the old days of Objective-C, you had ivars, and if you wanted to let some other class set or read them then you had to define a getter and a setter.
As I explained to you, with properties you get the setter and getter for free (almost!) along with an instance variable. So when you define a property, you can set the atomicity as well as assign/retain/copy memory management semantics.
Most people leave the ivar name the same as the property name, but it can be made to be something else when you write your #synthesize statement (i.e., #synthesize foo=_foo; means make an ivar named _foo for the property foo).
Note that as of Xcode 4.6, you do not need to use the #synthesize statement - by default will the compiler prepend the ivar's name with _. So #synthesize is no longer recommended by Apple for new code.
In both cases the assigned value will be retained, since you are assigning it to a strong variable. (Strong is the default for variables that reference object instances)
In the first example the method -setMyArray: will be called, which in the case of a generated setter will store the value to _myArray. In the second case, -setMyArray: will not be called.
For the given code the object already assigned to _myArray will have its reference count properly decremented when the _myArray is set again. (The existing strong reference to the object will be deleted.)
That first call will call the setter while the second will not, however both calls will overwrite the ivar _myArray. For example, if you did self.myArray = #[#"Hello"]; and then _myArray = #[#"World"], printing out both self.myArray or _myArray will print #[#"World"].
If you instead write your own method -(void)setMyArray;, It could possibly do different things, but then you also won't get the private ivar _myArray without declaring it yourself.

"property is backed by an ivar" ? What technically does that mean?

So ... I'm still fairly new to Objective C ... taking some iTunes U corses ... doing some exercises and all ...
But when you uses to do #synthesize myProperty = _myIvarPropertyNameToUse; ... iOS 5 would create an ivar that would "back" the property.
What exactly is going on here as far as where things sit in memory ...
(1) Is the ivar a true variable? ... or is it a pointer to the location of the property in the object?
(2) The property is on the heap, (being part of the object), right? Is the ivar on the heap as well?
I think I may be losing the big picture ... what's the point of having a property backed by an ivar?
thanks,
An Objective-C object is just a C struct that is allocated on the heap (well, more or less). When you declare an instance variable (ivar), it is defined as an offset into that struct. So if you manually declared some ivars like this (don't do it this way anymore, but it illustrates the point):
#interface Foo : NSObject {
NSString *ivar1;
NSString *ivar2;
}
Then when you +alloc a new instance (call it foo), the struct will be some header followed by the ivars of NSObject followed by memory for ivar1 followed by memory for ivar2. ivar1 will be the foo point plus some offset. (This isn't exactly true anymore, but stay with me; it's simpler to understand the old implementation.)
Since foo is a pointer to a struct, you can actually refer directly to this offset pointer as foo->ivar1. It really is a struct. Never do this, but it is legal syntax.
Inside of the #implementation block, ivar1 is automatically translated to self->ivar1. Don't worry too much about how self is implemented, but trust that it's a pointer to your struct. Again, never use this -> syntax. It's an underlying implementation detail (and isn't always possible anymore; see below).
OK, so that's what an ivar is. In the old days (ObjC 1.0), that's actually all we had. You declared your ivars, and then you hand-created accessor methods that would set and return their values.
Then ObjC2 comes along, which in some cases also gave us something called the non-fragile ABI. That changes the underlying implementation of ivars somewhat, so you can't always actually use -> anymore. But you shouldn't have been using it anyway. Even so, it's simpler to pretend things are the old way. More to the point, ObjC2 added this new thing called "properties." A property is just a promise to implement certain methods. So when you say:
#property (nonatomic, readwrite, strong) NSString *property;
this is almost identical to saying the following:
- (NSString *)property;
- (void)setProperty:(NSString *)aProperty;
(The difference is very seldom important.) Note that this doesn't provide an implementation. It doesn't create ivars. It just declares some methods.
Now in ObjC1, we wrote the same accessor code over and over and over again. You had 20 writable ivars, you wrote 40 accessor methods. And they were almost identical. Lots of opportunities to mess up. And a lot of tedium. Thank goodness for Accessorizer.
With ObjC2, the compiler would give you the most common implementation for free if you added #synthesize. It would automatically make an ivar with the same name as the property, and write a getter and (if needed) setter to read and write that ivar. Passing =_property just changes the name of the ivar used. We call this the "backing ivar."
Now, in the latest version of the compiler, you don't even need #synthesize. This pattern is so insanely common, and has been for decades, that it is now the default unless you tell the compiler not to do it. And it automatically synthesizes an ivar with a leading underscore (which is best practice).
The one other piece of information you should know is that you should always use the accessor to access the ivar, even inside of the object. The only exceptions are in the init and dealloc methods. There you should directly access the ivar (using the leading underscore).
Just to be clear, when you do #synthesize myProperty = _myIvarPropertyNameToUse;, your only changing the name of the backing ivar. The line #synthesize myProperty; would also create a backing ivar, but it would be called myProperty, instead of _myIvarPropertyNameToUse...
The backing ivar is part of the object, so yes it's on the heap. It can be used as a true variable, meaning you can get and set it in the object code.

Clarification on custom init methods / pointers in general for objective c objects

When I have my own init method with synthesized properties as such:
#property (copy, nonatomic) NSString *bookName;
#property (strong, nonatomic) NSMutableArray *book;
When I want to initialize with my own custom initializer I am shown to write it like this:
-(id) initWithName: (NSString *)name
{
self = [super init]
if (self) {
bookName = [NSString stringWithString: name];
book = [NSMutableArray array];
}
return self;
}
Now I want to clarify something. I know why it uses the stringWithString method, because instead of just passing the address to the passed in string it'll create a new object so that it owns the string itself. Could I not also just write it like so:
self.bookName = name;
Doing this should use the synthesized method and actually create a new object right? Basically both accomplish the same thing. I ask because there are methods else where that show doing it both ways so I just want to make sure there are no other issues that could crop up with using one way or the other. They both appear to do the same thing in different ways (using the synthesized method vs directly modifying the class variable but creating a new object in memory for it).
I'll also point out that this is in an ARC environment.
(Note that I am assuming the above is ARC code; otherwise it is incorrect.)
You should almost always use accessors to access your ivars (even in ARC). However, there is some controversy about whether init should use accessors or directly access its ivars. I have switched sides in this controversy, but it's not an obvious decision IMO.
The primary argument for not allowing init to use accessors is that it is possible that a future (unknown) subclass might create side-effects in the accessor. You generally don't want side effects happening during your init. For instance, you probably don't want to post change notifications when you're setting something to its initial value, and it is possible that your object is in an "undefined state" and would be dangerous to read at this point.
That said, and while this argument did finally sway me, I have never once encountered this situation on numerous projects of various sizes with several teams. I have many times encountered developers failing to retain when setting their ivars in init (as you have done above, and which would crash if it is not ARC). This is why for a long time I recommended using accessors even in init. But in theory it does create a danger, particularly if you are a closed-source framework writer (i.e. Apple). And so, for my own code I now avoid accessors in init. If I were working with a more junior teams on older retain/release code, I would probably still have them use accessors in init. It's just avoided so many crashes in my experience.
It is not controversial that you should avoid calling accessors in dealloc, however. This definitely can lead to bizarre side-effects in the middle of destroying your object.
You are correct, since bookName is declared as copy, assigning self.bookName would make a copy of the string passed in. I am not certain that copying would go through exactly the same code path as the [NSString stringWithString: name], but it would achieve the same purpose of creating a copy of the original string, shielding you from unexpected consequences of users passing in a mutable object and mutating its value behind your back.
Because the declared property is copy then yes, they are doing the same thing.
Many times however, it is a strong and then there would be a difference between the two methods so the first method would be the "correct" way of doing it.

How does accessing ivars directly differ from using an accessor?

So in some of the codes I see, they access an objects ivar directly instead of using accessors . What are the advantages of using them instead of accessors?
So how would this
thing = object->ivar
differ from this?
thing = object.ivar
Thanks.
First let me say, I totally loathe the Objective-C dot notation. It sacrifices understandability for brevity and that is a bad thing. In fact, the other two answers here both show evidence of the kind of confusion dot notation introduces.
Having got the rant out of the way, I'll now try to answer the question.
Under the hood, Objective-C objects are implemented as pointers to C structs. This is why
obj->ivar
sometimes works. Given that it's a C struct
(*obj).ivar
should also work exactly as you would expect for C. Having said that, you can make ivars private or protected, in which case using the above outside a scope where they are visible will cause a compiler error.
The dot operator when applied to an Objective-C object (which is a pointer don't forget) has a totally different meaning. It's syntactic sugar for sending an accessor message to the object meaning that:
foo = obj.property;
obj.property = foo;
is identical in effect to
foo = [obj property];
[obj setProperty: foo];
That is all there is to dot notation. If you go through your code changing all instances of the first form to instances of the second form, you have done everything the compiler does wrt dot notation.
In particular
you do not need a declared #property to use dot notation. You can declare the set and get accessors in the traditional way as Objective C methods, although it is definitely best practice to use #property declarations for things that are logically properties.
you do not need a backing instance variable. There's no reason why your getters and setters can't calculate values.
Given the above, the major difference between obj->ivar and obj.ivar is that the former modifies the ivar directly and latter invokes an accessor, this means that the latter can do any memory management stuff needed (retains, releases, copies etc) and can also invoke key value observing.
This is one thing with a huge difference between c/c++ and objective-c.
In C/C++ the . accesses the variable directly and the -> accesses the variable if it's a pointer to the variable, so basically it is the same.
In Objective-C the . is a shortcut to access the property using the setter and getter function and it is always using those functions. You can't access ivars with it if there is no property with that name.
Some say it's "dirty" to allow direct access to the variables. If more people work on the code it's "cleaner" to use accessors because it might be easier to debug where variables are changed since you can always break in the setter.
You can even do "bad" things with it, like:
NSArray *array = [NSArray alloc] init];
int count = array.count;
array.release;
this will technically work, because the array.release is a shortcut for [array release] but it is bad style to use . for other things then properties.
The advantage of properties is that they call methods that work with your ivars, in stead of calling the ivars directly, so you can do things like this:
-(void)setFrame:(CGRect)frame
{
if([self frameIsValid:frame])
{
if(self.flipsFrames)
{
frame.size = CGSizeMake(frame.size.height,frame.size.width);
}
[super setFrame:frame];
[delegate viewSubclass:self ChangedFrameTo:frame];
}
}
Four advantages shown here are:
The possibility to override
The possibility to check a given value
The possibility to alter a given value (use with caution)
A way to react to calls
Another advantage:
-(NSInteger) amountOfMinutes
{
return amountOfSeconds * 60;
}
You can use 1 ivar for multiple properties, saving memory and preventing/reducing redundancy, while keeping useful different formats.
There's not really an advantage to using ivars, except when you don't want to use a property so your class is more encapsulated. That does not make it impossible to reach, but it makes it clear it isn't supposed to be reached.
All ivars are private. There is no way to access them directly from outside the object. Therefore, both of your code samples are equivalent, in ObjC terms.
When you call object.ivar, what you are really doing is calling object's ivar selector. This may be either a getter method that you wrote yourself, or more likely, a synthesized getter method that you created with #synthesize.
thing, however, is an ivar. Your code would be calling the ivar selector on object and assigning the result directly to your instance's thing ivar.
If you had instead written it as self.thing = object.ivar, then you would be using your instance's setter method to assign to thing.
Some of the advantages of using accessors (specifically, synthesized properties) in ObjC are KVO/KVC compliance; better concurrency support; access control (readonly, readwrite); as well as all of the advantages that accessors give you in any other OO language.

Using instance variables with Modern Runtime

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...