Are declared property attributes overridden when implementing custom accessor methods? - objective-c

Suppose I declare a property like so
#property (nonatomic, copy) NSObject *property;
Then I create a custom setter method
- (void) setProperty:(NSObject *)property
{
_property = property;
// Some more code here
}
Does the compiler interpret the copy keyword so that this setter function is equivalent to this?
_property = [property copy];
Or is it my responsibility to write it this way so that the keyword matches the behavior?

From "4.1.1 Property declarations" in the Clang/ARC documentation
(emphasis added):
copy implies __strong ownership, as well as the usual behavior of copy semantics on the setter.
...
A property’s specified ownership is preserved in its metadata, but
otherwise the meaning is purely conventional unless the property is
synthesized.
If a property is synthesized, then the associated instance variable is
the instance variable which is named, possibly implicitly, by the
#synthesize declaration. If the associated instance variable already
exists, then its ownership qualification must equal the ownership of
the property; otherwise, the instance variable is created with that
ownership qualification.
So in your case, with a custom setter, declaring the property as "copy" implies that the associated
instance variable _property is __strong but nothing else.
It is your responsibility that the setter actually makes a copy, for example:
- (void) setProperty:(NSObject *)property
{
_property = [property copy];
// Some more code here
}

Related

ARC: property vs ivar: copy, weak

From reading Property vs. ivar in times of ARC, I understand that ARC will use the __strong ownership qualifier when I directly get or set a strong property's autosynthesized associated instance variable but will neither call custom getters or setters nor trigger KVO.
But, if I declare a property as weak like so:
#property (weak, nonatomic) id <XYZExampleViewDelegate> delegate;
Will the autosynthesized associated instance variable take on the __weak ownership qualifier?
For example, will _delegate = delegate (vs self.delegate = delegate) in my implementation of
- (id)initWithDelegate:(id <XYZExampleViewDelegate>)delegate
perform assignment according to the __weak qualification?
What about for a property declared with copy?
Yes, the property modifier weak implies __weak ownership. A property's associated instance variable (or backing ivar) is created with the ownership qualifier implied by the property's modifier. See Clang documentation on ARC property declarations for a list of property modifiers and which ownership qualifiers they imply.
The property modifier copy implies __strong ownership. So, when setting the backing ivar directly, the new pointee is retained but not copied. To copy it, use the setter.

Overriding setter methods (strong vs. assign) using ARC

When defining a strong property in an interface, like so:
#property (nonatomic, strong) UIColor *petColor;
It is no longer required to add #synthesize, or #dynamic, or to manually define the internal ivar as _petColor, this all just works. The setters/getters are automatically generated, and you can access _petColor internally without any additional code.
However, I'm a little confused as to how (if at all), when overriding a setter, ARC knows whether to insert the retain/release calls depending on whether the property is strong or weak? For example, if I have two properties:
#property (nonatomic, strong) UIColor *petColor;
#property (nonatomic, weak) SomeClass *petDelegate;
If I want to override the setters for these properties, it seems they would be almost exactly the same?
- (void)setPetColor:(UIColor *)theColor {
if (![theColor isEqual:petColor]) {
_petColor = theColor;
}
}
- (void)setPetDelegate:(SomeClass *)theDel {
if (theDel != petDelegate) {
_petDelegate = theDel;
}
}
Is this correct? And if so, is ARC automatically inserting the proper retain/release calls in both of those setters, or only in the overridden setter for the strong property?
Further: Does the weak property behavior differ, in this situation, from the assign property behavior?
It's even simpler than that. When synthesizing, the instance variables get the respective qualifiers:
#implementation MyClass {
// this is what is added by the auto synthesize
UIColor * __strong _petColor;
SomeClass * __weak _petDelegate;
}
So when you assign to the instance variables using own setters, everything is fine, except for the copy qualifier. That one cannot be used for an instance variable, so then assign a copy to the instance variable.
Regarding assign (or the equivalent unsafe_unretained) for object properties, the instance variable would just be a pointer, and be synthesized to
SomeClass * __unsafe_unretained _petDelegate;
So if the object assigned to the property is deallocated, the pointer would not be set to nil as with weak, but point to where the deallocated object lived before. That may lead to crashes. As a rule of thumb, if you write your code for iOS 5 or later, always use weak instead of assign or unsafe_unretained on object properties.
Setting the strong, weak, or assign attributes of a property tells the compiler the storage class of the underlying data. If that is an auto-generated iVar, then it maps as following:
strong -> __strong
weak -> __weak
assign -> __unsafe_unretained
If you don't use an auto-generated iVar, then whatever data you have feeding the property is expected to conform to those storage class mappings.
See: Objective-C Automatic Reference Counting (ARC) : Property declarations

Properties and accessor methods without member in 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

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.

Property vs. ivar in times of ARC

It is my understanding that setting an ivar now retains the object being assigned to it, since setting variables defaults to the strong qualifier. Because ivars are in the scope of the object they are declared in and strong retains objects within the scope of the variable, this means the ivars value would never be released while the object containing the ivar is still alive.
Is this correct?
If so, am I right in thinking that there is, in terms of memory management, no difference between a retaining (strong) property and a simple ivar anymore?
If a variable:
Is declared in a class using ARC.
Is used solely for class implementation (not exposed as part of the class interface).
Does not require any KVO.
Does not require any custom getter/setter.
Then it is appropriate to declare it as an ivar without a corresponding #property/#synthesize, and to refer to it directly within the implementation. It is inline with Encapsulation to declare this ivar in the class implementation file.
// MyClass.h
#interface MyClass : ParentClass
#end
// MyClass.m
#implementation MyClass {
NSString *myString;
}
- (void)myMethod {
myString = #"I'm setting my ivar directly";
}
#end
This ivar will be treated as __strong by the ARC compiler.
It will be initialized to nil if it is an object, or 0 if it is a primitive.
You can't use KVO and do custom getter and setters with instance variables other than that they are very similar when using ARC.