Do the ARC compiler automatically determines whether to retain or assign in overridden class depending on property attributes? - objective-c

I don't know assembler well enough to understand so complicated code as Assembly for whole project, but I noticed that if I put strong attribute to the property, a _objc_storeStrong call shows up near the line in my setter where I change my properly;
#interface ClassName : NSObject
#property (strong, nonatomic) NSSet *mySet;
#end
#implementation ClassName
#synthesize mySet;
-(void)setMySet:(NSSet *)newMySet
{
mySet = newMySet;
//do stuff
}
#end
So? am I right? Do the ARC compiler automatically determines whether to retain or assign in overridden class depending on property attributes?

In short, yes. Because you set the property as strong, it will be retained by the object. If you declare the property as weak, the implied (synthesized) variable is __weak NSSet *mySet and that won't retain the object, but it will be a auto-zeroing pointer.

Related

Can a property be declared with #synthesize only without #property?

I found the following code in my project (using ARC). It looks like there is no property adDisplay declared. Only a synthesized statement and the compiler doesn't complain about it.
#interface MyClass() <MyProtocol> {
AdDisplay * _adDisplay;
}
#end
#implementation
#synthesize adDisplay = _adDisplay;
...
#end
Do I need to add
#property (nonatomic, strong) AdDisplay * adDisplay;
if I want to make sure adDisplay is strongly retained?
thanks
Update: it is declared in the protocol indeed. Does that count as instance variable?
A property in Objective-C is a name for a pair of methods: a setter and a getter. Declaring a property means saying that these two methods exist (for readwrite properties).
There does not have to be any real storage or memory management. Historically, under manual memory management, assign, retain, or copy would affect how the methods are synthesized.
However, under ARC, this is no longer needed. When you declare a property as strong or weak, it does not affect the body of the method, but only the type of the ivar.
Since you have an ivar declared manually
AdDisplay * _adDisplay;
(as strong)
then strong or weak inside the #property declaration won't have any real effect, only as a documentation for the API consumers.
The following would also work:
#interface MyClass() <MyProtocol>
#end
#implementation
#synthesize adDisplay;
#end
Also note this used to be a common memory leak problem when migrating projects from MRC to ARC. A property declared as weak, with an ivar declared as strong.

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

Which attribute to use as property for class

#property (nonatomic, assign) Class aClass;
or
#property (nonatomic, retain) Class aClass;
Note: "Class" is that "Class" defined in objc.h
and does it need a release in the dealloc method?
Since it's a pointer to a class object, and class objects live for the lifetime of the app, memory management actions like retain and release have no effect on it. So it shouldn't matter whether you use assign or release. It would be simpler to use assign.
If you use retain, the compiler will generate an object for you and retain it in the class. For such cases you should release it in the dealloc.
Do not forget to add the synthesize though, otherwise you won't get any getter and setters.
Read more here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
And here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW9

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.

how to release "delegate" memories in objective-c?

For my project,am creating delegate class. When i assign obj.delegate = self, [self retainCount] get increased by one. So that assigned object having retain count is 2. how should release delegate object and assigned object retaincount is 1?
Regards
Srini
It's the normal convention that delegates are not retained. This is mainly because the usual pattern is that the owner of the object is often also its delegate and if the delegate were retained, you'd get a retain cycle.
If you are using a property, declare it like this:
#property (assign) DelegateType delegate; // replace "DelegateType" with whatever type you need
And remove the line in -dealloc that releases the delegate.
If the accessors are synthesised, you are now done. If not, make the accessors assign accessors e.g.
-(DelegateType) delegate
{
return delegate;
}
-(void) setDelegate: (DelegateType) newValue
{
delegate = newValue;
}
In general you shouldn't be retaining delegates. The usual pattern is just to assign them. Otherwise, as you note, you'll get all kinds of problems with release cycles and so forth.
How are you defining the accessor for the delegate
#property (nonatomic, retain) Whatever *delegate;
or
#property (nonatomic, assign) Whatever *delegate;
if it is the former then the retain count will be incremented which is not what you want to be doing with a delegate. It's the responsibility of the creator to keep hold of the delegate. You are only being told about it, and should not retain it. Its only the ability of Obj C to send messages to nil without failing that means you should not be checking the reference before use too.