Properties and accessor methods without member in objective-c - objective-c

I was just going through properties documentation in the link: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
The section' You Can Implement Custom Accessor Methods' describes that Properties don’t always have to be backed by their own instance variables. The example of fullName also does not use its own corresponding member.
Won't the compiler implicitly create a member when a property is defined (_propertyName)?

If you create a property using #property, then an ivar is created automatically and its setter and getters are created by LLVM compiler.
Whereas when you create an ivar, you have to create a setter/getter for it. Typically you do with #property and leave rest on the compiler.
However in some cases you create ivar and property with different name and put a reference to it as :
#synthesize boxDescription=boxName;
Now boxName is accessor for boxDescription, now you cant use boxDescription in your code.

if you override the default setter and getter, and you dont provide the #synthesize (and as well you dont access the _ivar), no variable is created for you by the compiler. in that case you have a property that is not backed by an ivar.
as a very random example:
#property (nonatomic) int x;
- (int)x
{
return 1;
}
- (void)setX:(int)x
{
NSLog(#"%d", x);
}
a more userfull usage can be if you have a facade for other classes, and you use this setter/getter to set/get those.
in case you don't override the set/getter and now that #synthesize is not mandatory anymore by default the compiler creates an ivar named _propertyname, you can override this behavious by #synthesize prop_name=ivar_name

Related

Do "atomic" and "nonatomic" attributes on properties have any effect if you use a custom getter/setter?

If I have a property declared in a class:
#interface MyClass : NSObject
#property (atomic) NSString *myString;
#end
And I implement custom getter and setter methods:
#implementation MyClass
- (NSString *)myString
{
// return something
}
- (void)setMyString
{
// do something
}
#end
Does the "atomic" attribute on the property declaration actually do anything? Or is it only used if an automatic getter/setter is actually created by the compiler?
Assuming the "atomic" and "nonatomic" keywords don't do anything for properties with custom getters and setters, is there any convention for what attribute we should use for those properties?
Does the atomic attribute on the property declaration actually do anything? Or is it only used if an automatic getter/setter is actually created by the compiler?
atomic is used only when a getter/setter is synthesized by the compiler. It is also used to check the consistency of accessors for readwrite properties:
Because the internal implementation and synchronization of atomic accessor methods is private, it’s not possible to combine a synthesized accessor with an accessor method that you implement yourself. You’ll get a compiler warning if you try, for example, to provide a custom setter for an atomic, readwrite property but leave the compiler to synthesize the getter.
is there any convention for what attribute we should use for those properties?
Apple does not require you to follow any convention, but you could use atomic and nonatomic attributes to document your own code. This would let readers of your code learn about the behavior of your accessors without looking into their implementation.

When should I use #synthesize explicitly?

As far as I know, since XCode 4.4 the #synthesize will auto-generate the property accessors. But just now I have read a sample of code about NSUndoManager, and in the code it noticed that the #synthesize is added explicitly. Like:
#interface RootViewController ()
#property (nonatomic, strong) NSDateFormatter *dateFormatter;
#property (nonatomic, strong) NSUndoManager *undoManager;
#end
#implementation RootViewController
//Must explicitly synthesize this
#synthesize undoManager;
I am feeling puzzled now... When should I add #synthesize explicitly to my code?
There's a lot of answers, but also a big confusion. I'll try to put some order (or increase the mess, we'll see...)
Let's stop talking about Xcode. Xcode is an IDE. clang is a compiler. This feature we are discussing is called autosynthesis of properties and it's an Objective-C language extension supported by clang, which is the default compiler used by Xcode.
Just to make it clear, if you switch to gcc in Xcode, you won't benefit from this feature (regardless from the Xcode version.) In the same way if you use a text editor and compile using clang from the command line, you will.
Thank to autosynthesis you don't need to explicitly synthesize the property as it will be automatically synthesized by the compiler as
#synthesize propertyName = _propertyName
However, a few exceptions exist:
readwrite property with custom getter and setter
when providing both a getter and setter custom implementation, the property won't be automatically synthesized
readonly property with custom getter
when providing a custom getter implementation for a readonly property, this won't be automatically synthesized
#dynamic
when using #dynamic propertyName, the property won't be automatically synthesized (pretty obvious, since #dynamic and #synthesize are mutually exclusive)
properties declared in a #protocol
when conforming to a protocol, any property the protocol defines won't be automatically synthesized
properties declared in a category
this is a case in which the #synthesize directive is not automatically inserted by the compiler, but this properties cannot be manually synthesized either. While categories can declare properties, they cannot be synthesized at all, since categories cannot create ivars. For the sake of completeness, I'll add that's it's still possible to fake the property synthesis using the Objective-C runtime.
overridden properties (new since clang-600.0.51, shipping with Xcode 6, thanks Marc Schlüpmann)
when you override a property of a superclass, you must explicitly synthesize it
It's worth noting that synthesizing a property automatically synthesize the backing ivar, so if the property synthesis is missing, the ivar will be missing too, unless explicitly declared.
Except for the last three cases, the general philosophy is that whenever you manually specify all the information about a property (by implementing all the accessor methods or using #dynamic) the compiler will assume you want full control over the property and it will disable the autosynthesis on it.
Apart from the cases that are listed above, the only other use of an explicit #synthesize would be to specify a different ivar name. However conventions are important, so my advice is to always use the default naming.
If you do not explicitly use #synthesize the compiler will understand your property the same way if you had written
#synthesize undoManager=_undoManager;
then you will be able to write in your code things like :
[_undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
This is the common convention.
if you write
#synthesize undoManager;
you will have :
[undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
Personally I stop using #synthesize, since it's not mandatory any more.
For me the only reason to use #synthesize is to link an iVar to a #property. If you want to generate specific getter and setter for it.
But in the given piece of code there is no iVar, I think that this #synthesize is useless. But now I think the new question is "When to use iVar ?", and I've no other response than "never" for this one !
When should I add #synthesize explicitly to my code?
Generally, if it's required: You will probably never hit a case where it's needed.
There's one case you might find it useful, though.
Say you're writing both a custom getter and setter, but want an instance variable to back it. (For an atomic property, this is as simple as wanting a custom setter: the compiler will write a getter if you specify a setter for a monatomic property, but not an atomic property.)
Consider this:
#interface MyObject:NSObject
#property (copy) NSString *title;
#end
#implementation MyObject
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
#end
This will not work, because _title doesn't exist. You've specified both a getter or setter, so Xcode (correctly) doesn't create a backing instance variable for it.
You have two choices for making it exist. You can either change the #implementation to this:
#implementation MyObject {
NSString *_title;
}
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
#end
Or change it to this:
#implementation MyObject
#synthesize title = _title;
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
#end
In other words, although synthesize is for practical purposes never necessary*, it can be used to define property-backing instance variables when you're providing a getter/setter. You can decide which form here you want to use.
In the past, I've favoured specifying the instance variable in the #implementation {}, but I now think the #synthesize route is a better choice as it removes the redundant type and explicitly ties the backing variable to the property:
Change the property's type, and the instance variable's type changes.
Change its storage qualifier (for instance, make it weak instead of strong or strong instead of weak) and the storage qualifier changes.
Remove or rename the property, and the #synthesize will generate a compiler error. You won't end up with stray instance variables.
*-I know one case where it was necessary, relating to splitting functionality across categories in multiple files. And I wouldn't be surprised if Apple fixes this, or even already has.
OK, when you create a property...
#property NSString *name;
Xcode will auto synthesise an iVar as if you had written...
#synthesize name = _name;
This means you can access the property with...
self.name;
// or
_name;
Either will work but only self.name actually uses the accessor methods.
There is only one time that auto synthesise does not work: If you overwrite but the setter AND the getter method then you will need to synthesise the iVar.
You are fine if you just override the setter or if you just override the getter. But if you do both then the compiler won't understand it and you will need to synthesise it manually.
As a rule of thumb though.
Don't make iVars.
Just use the property.
Don't synthesise it.
Property synthesis is required when a property is declared in a protocol. It will not be automatically synthesized in an implementing interface.
Thanks for clarifying that. I had a similar problem.
#synthesize firstAsset, secondAsset, audioAsset;
#synthesize activityView;
So now, having commented them out, I went through and replaced each occurrence with, for example
self.firstAsset It seems I could also use firstAsset, but I find I miss seeing the "" too often.
Xcode doesn't require an explicit #synthesize declaration.
If you don't write #synthesize its the same as doing :
#synthesize manager = _manager;
The sample code might've been old. They'll update it soon.
You can access your properties like :
[self.manager function];
This is Apple's recommended convention. I follow it, and I recommend that you do too!

Autosynthesized property 'delegate' will use synthesized instance variable '_delegate', not existing instance variable 'delegate'

I'm following the guide here to create a custom delegate. It runs fine but I get the following warning in xcode
DetailViewController.m:23:1: Autosynthesized property 'delegate' will
use synthesized instance variable '_delegate', not existing instance
variable 'delegate'
Can anyone advise how to get rid of the warning
The most idiomatic way to handle this situation is simply to remove your delegate ivar declaration. If you were using your delegate ivar, you should use the implicit ivar _delegate instead.
Why does this work?
As of Xcode 4.4 (LLVM Compiler 4.0), instance variables and accessor methods are synthesized automatically for a property if the #synthesize directive is not used explicitly for that property. As Apple's documentation on encapsulation states
By default, [...] accessor methods are synthesized automatically for you by the compiler, so you don’t need to do anything other than declare the property using #property in the class interface.
The ivar that is used for a property (which is gotten and set by the automatically synthesized property accessor methods) is named _<propertyName> (i.e. the ivar's name is the property's name prefixed with an underscore).
In this case the property name is delegate, so the the ivar that is used is _delegate. This is already happening in your code. When you call -delegate and -setDelegate:, this ivar _delegate will be gotten and set.
However, you've also declared your own ivar delegate. Of course, the ivar you explicitly declared (delegate) will not be gotten and set by the instance methods -delegate and -setDelegate: since the automatically synthesized ivar (_delegate) is being gotten and set. However, (almost always--if it wasn't, your code is ambiguous) your intent was for your ivar delegate to be the thing that your property's accessors would get and set. Luckily, the compiler is clever enough to notice what you've done, and that's why it is emitting this warning:
warning: autosynthesized property 'delegate' will use synthesized instance variable '_delegate', not existing instance variable 'delegate' [-Wobjc-autosynthesis-property-ivar-name-match]
It's telling you that your property delegate will use the automatically synthesized ivar _delegate rather than the ivar that you explicitly declared, delegate.
So if you simply delete your delegate ivar, the compiler will stop emitting this warning. If you were using the delegate ivar directly (not through the property), start using _delegate instead.
A minor variation on this option is to explicitly declare the same ivar (_delegate) that the automatic synthesis of the delegate property is creating. You can do this by replacing
#interface TheClass : TheSuperclass
{
//...
id<TheDelegateProtocol> delegate
//...
}
#end
with
#interface TheClass : TheSuperclass
{
//...
id<TheDelegateProtocol> _delegate
//...
}
#end
This works because automatic synthesis of a property will always use an ivar whose name is the property's name prefixed with an underscore. If no such ivar exists, the ivar will be generated. If it does exist, it will be used.
If instead you would prefer that your property's accessors set and get your ivar delegate you can add an #synthesize directive to your class' #implementation to tell the compiler to do just this:
#implementation TheClass
//...
#synthesize delegate = delegate;
//...
#end
The line #synthesize delegate = delegate; tells the compiler to use the ivar delegate (the right hand of the assignment) in the accessors for the property delegate (the left hand side of the assignment).
You can also omit the right hand side of the #synthesize assignment and just write
#implementation TheClass
//...
#synthesize delegate;
//...
#end
This works because a property with a manual #synthesize which does not explicitly specify the ivar to be gotten and set by its accessors (such as #synthesize delegate;) will use an ivar with the same name as the property, NOT prefixed by an underscore. This has to do with backwards compatibility.
There's another method and this one worked for me:
#property (nonatomic, unsafe_unretained) id <MyDelegate> delegate;
You can then add this to the implementation without error:
#synthesize delegate;
Also: This is ARC compliant.

use of #property and #synthesise?

I was wondering what the point of #property and #synthesise were. At the moment I use the following to declare something:
//Class.m
#import "Class.h"
CCNode *node;
#implementation
//init, etc..
But I have seen others use:
#property (nonatomic, etc..) CCNode* node;
#synthesise (nonatomic, etc..) node;
//I am not too sure on how this type of declaration works, please correct me on how it's done.
They both seem to work in the same way, what are the advantages of the #property and #synthesise way? Do they do different things, if so, what?
#property and #synthesize are two objective C keyword that allow you to easily create your properties and therefore avoid to write by hand getters and setters methods of the property.
The #property define the property itself, should be placed in the header file and can get some attributes (as for example : strong, nonatomic, retain assign, copy), the #synthesize should be placed into the implementation file and tell the compiler to generate the body of getter and setter method.
These two keyword are extremely useful when coupled with the right use of their attributes, because they take care of the generation of the property code and most of all they take care of the memory management of the property.
#property - create the declaration of your getter and setter.
#synthesize - provide the definition of getter and setter based upon the parameters which are passed inside property.
Check this out, there are a lot more details about the same present there - https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
on using #property the compiler will take care of declaring getter and setter methods based on readonly and readwrite
readonly -> getterMethod
readwrite -> both setter and getter method
on using #synthesize the compiler will take care of defining getter and setter methods
If you have an instance variable (ivar) in your class, you can't access it from other classes usually. So you have to make public accessor methods (getters and setters). They look something like this:
Setter:
- (void)setMyVariable:(SomeClass *)newValue {
if (newValue != myVariable) {
[myVariable release];
myVariable = [newValue retain];
}
}
Getter:
- (SomeClass *)myVariable {
return myVariable;
}
This was the way you had to do it before Objective-C 2.0. Now you can use #property and #synthesize to speed this up. It's basically just a shortcut.
In the header you use #property to define what kind of setters you want. Should the setter retain the passed value (like in my example) or copy or just assign?
And in the implementation you just write #synthesize to make the compiler include the automatically created getters and setters at that position. Usually at the top of your implementation.
My feeling is that all iVars should have an associated underscore synthesised property (using an _iVar prevents accidental direct access), and all access to the iVars, apart from init and dealloc methods, should via the property.
IMHO the big win is memory management - it's safer and much easier as there is no need to remember which iVars have been retained.
And think of how much work is required to code an accessor - 4 lines for getter and 2 for a setter.
At some point in the future #synthesize is likely to be optional, so all you'll need is the #property.

Creating Properties in Obj-C, how do I write the default Getter?

I'm just starting to learn Objective-C, one thing I'm trying to learn is good Property use. I'm currently trying to create some properties with custom setters. This is how far I've gotten:
#interface MyClass : NSObject
#property (nonatomic, assign) int myNumber;
#end
#implementation MyClass
#dynamic myNumber;
- (int)myNumber {
return ???;
}
- (void)setMyNumber:newNumber {
myNumber = newNumber;
// custom stuff here
}
I really just want to implement a custom setter, I'm fine with the getter being default. However, how do I access the variable directly? If I put "return self.myNumber", won't that just call the getter method and infinite loop?
Property access functions are only called when using the x.p notation. You can access the instance variable backing the property with just p (in Objective C, all members have the class instance variables in scope). You can, if you really want, also access via the pointer deference notation ->. So, any of these two:
return p;
return self->p;
However, you needn't use #dynamic here. #synthesize is smart, and will only create defaults if you've not provided them. So feel free to just
#synthesize p;
Which will create the getter, but not the setter in this case.
- (int)myNumber {
return myNumber;
}