This simple question is bugging me. Are getters the same for
#property (nonatomic, retain) NSString *name
#property (nonatomic, copy) NSString *name
- (NSString*) name{
return name;
}
According to the documentation
A property declaration, however, provides additional information about
how the accessor methods are implemented (as described in “Property
Declaration Attributes”).
Both the getter and the setter behavior are defined by property declarations. In your example that is correct since it is defined nonatomic but if nonatomic were missing from the declaration it would would be implemented similar to this
- (NSString*) name{
[_internal lock]; // lock using an object-level lock
id result = [[name retain] autorelease];
[_internal unlock];
return result;
}
This of course is only true if you use #synthesize and do not override or change the getter and setter methods.
Yes, as the other answers state, the getters are the same. The options retain, copy, and assign determine how to generate setters, but not the names even of those.
If you want to use a different getter name, for instance if you have a BOOL such as the UIApplication property idleTimerDisabled, then you do this by specifically assigned the getter name:
#property(nonatomic, getter=isIdleTimerDisabled) BOOL idleTimerDisabled
Without an override such as this, the getter name is always the property name.
Yes, they are the same. retain, copy, and assign only give the compiler instructions on how to generate setters, not getters.
Yes, copy and retain only affect the setter and not the getter. On a side note, you should chose copy instead of retain for immutable objects like NSString.
If you're using ARC (Automated Reference Counting), then the getters should all look like what you have above. However, the new standard with ARC is to use strong and weak instead of retain and assign, respectively. retain and assign will still work and are synonymous with the strong and weak, but any newly generated files will use those words instead, so it's important to understand what they mean.
If you aren't using ARC (still an option, even in iOS 5 and Lion) getters can be different depending on retain, copy, or assign.
retain and copy both look like:
- (NSString *)name {
return [[name retain] autorelease];
}
assign is pretty basic, but is usually used more for weak references (like delegates):
- (id)delegate {
return delegate;
}
I went into some detail on this because it's important to understand when using ARC, the code for all 3 look the same, but the behavior is still very much like what's written above. If you're using atomic instead of nonatomic then you need to add some locking/unlocking lines to make the method thread-safe. In any case, it's generally better to use the default accessors generated with #synthesize unless you want to do something really tricky.
Yes, they are. The getter name dependce only of properties name.
Related
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!
I store some data in NSUserDefaults and keychain and I have a wrapper. For example
- (NSString *)userPassword
{
return [UICKeyChainStore stringForKey:KEY_USER_PASSWORD];
}
- (void)setUserPassword:(NSString *)userPassword
{
[UICKeyChainStore setString:userPassword forKey:KEY_USER_PASSWORD];
}
How should properties definition look like? Now I use as follows
#property (nonatomic, strong) NSString *userEmail;
But now I have a doubt if I should use strong statement there since I haven't an ivar for it.
Thanks in advance.
strong or weak both will be fine.
Its your custom method, this implies that you are overriding the compiler's method, or rather compiler will not create methods for those properties.
EDIT:
One more thing for you :)
Is there any advantage of having atomic property for saving in keychains/userdefaults?
You can use strong properties.
Here you are implementing your own setter and getter which means you are only overriding the methods of compiler so If you want to use you can else it is also fine.
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.
In my implementation I have getters and setters like below. I want to use properties and synthesize the getters and setters but have a few questions.
- (NSString *)title {
return title;
}
- (void)setTitle:(NSString *)value {
if(title != value) {
[title release];
title = [value retain];
}
}
If I was to convert that to a property, what attributes would I use? Am I right in thinking:
readwrite so both getters and setters are present
retain so that it increase the retain value of the value string so the object don't lose it.
Am I right with the above?
One final thing. I have the method below ...
- (void)setReleaseDate:(NSString *)value {
// YYYY-MM-DD HH:MM:SS +HHMM
if([releaseDate description] != value) {
[releaseDate release];
releaseDate = [[NSDate alloc] initWithString:value];
}
}
Am I right in thinking I still have to include that method because it contains code that the synthesized getter would not include?
Thanks.
For your title property, you can declare it in your class interface as follows:
#property (nonatomic, retain) NSString* title;
Which is the same as the following:
#property (readwrite, nonatomic) NSString* title;
readwrite is a default setting. Most of the time you will want setters for your properties, so for the times when you don't you would use the non-default readonly to specify this.
The nonatomic part basically means that the accessors will be faster, and is typically used. You can find out more information about this here: What does the property "Nonatomic" mean?.
For your second question, you can implement your own accessors if you wish. If you do this then it kind of 'overrides' the accessor that would be generated by Objective-C. Remember that you have to keep to the naming conventions. So in your example, the "setReleaseDate:" method you've defined would be used for the setter method for the property "releaseDate" - which is completely correct! :) The problem you have though is that you're passing an *NSString** to set the date, which means that this method won't override the default setter that would be used if you synthesized the property. You have to pass a value of the same type as the one you're setting as the single argument, so for this case you would have to pass an *NSDate**.
You must also ensure that if you provide your own implementation of an accessor that it does what is declared in the interface. I presume your releaseDate property should be declared as retain.
Your assertion about using readwrite as well as retain is correct as it would create semantically equivalent code to what you have posted.
The releasedate property setter can't be synthesized as you're transforming a NSString into a NSDate to store it, that also avoids common issues with NSString properties, for which you'd better use copy to avoid problems with NSMutableString.
Other than that, your code is fine, except that for string comparison you may want to replace the simple pointer check != with isEqualToString, see Comparing Strings in Cocoa.
It is common, though not always required, to use copy semantics for NSString properties, to avoid issues with NSMutableString objects being changed behind your back.
Otherwise, you seem to be pretty much on top of it.
If you declare a property with a retain attribute, do you need to release the property before you set it to nil?
What does the #synthesize directive do?
You do need to release the (retained) object before setting another object or nil in your property var but this is done by the accessor, if you like this.
self.myVar = nil;
What #synthesize does is to create accessor methods automatically for you (In case you don't define them)
so, if you wrote your property as:
#property (nonatomic, retain) NSObject *property;
then you can think that synthesized accessors will be something equivalent(I said equivalent because we don't certainly know how this is done... for more info read doc below) to the following:
- (void) setProperty:(NSObject *)aProperty{
if(property != aProperty){
[property release];
property = [aProperty retain];
}
}
- (NSObject*) property{
return property;
}
This part is SUPER important and I would suggest to spend as most time available to learn about this. (Also read copy and assign)
Apple doc on Properties
You do not need to release a retained property before setting it to nil as long as you use a setter that does the release for you. If you've declared a property with retain, the synthesized setter will do the release for you. And that brings us to the #synthesize directive. It simply tells the compiler to write the setters and getters for you using the attributes you've specified in #property.
No, in fact you don't need to release it at all. That would be a bug. You don't even have to set it to nil, unless you really want to control when it's released (before your own class' release, that is).
Creates the getter and setter methods for you, presumably in an optimized way.
For more information I suggest you read the relevant page in the guide.