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.
Related
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
#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
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.
Recently some example from Apple looks something like this:
#interface ViewController : UIViewController
{
**// Notice no more ivar here.**
}
#property (nonatomic, retain) IBOutlet UIWebView *webView;
#end
#implementation ViewController
#synthesize webView = _webView;
...
- (void)dealloc
{
[_webView release];
[super dealloc];
}
My question is why aliasing the webView to _webView, and release in the dealloc since there is no ivar named _webView?
One more question, if I declare a property that has no related ivar, do I need to release it in dealloc?
When you #synthesize a property that doesn't have an associated ivar (whether you say #synthesize property or #synthesize property=_property), an ivar is generated for you. The default is to use the same name for the ivar as the property itself. If the property is a retain property, then you have to release the object in -dealloc or you'll have a memory leak.
Apple's convention is to name ivars (whether declared explicitly in the interface or implicitly in an #synthesize) with an underbar to indicate the private nature of the ivar. IMO it's also helpful to ensure that people use the ivar only when they intend to (since for some coders it seems to be easy to accidentally type myproperty when you mean self.myproperty, which can create significant bugs).
The answer to your last question is basically yes, though technically the answer is 'sometimes'. You only have to release the object if there is an object stored in an ivar that was retained. That's most of the time. However, properties are just a shortcut for invoking methods named 'myproperty' and 'setMyproperty' (etc), so it's possible to have a pair of methods with those names and an associated property that doesn't actually have an ivar paired with it. But if you're declaring properties with the retain attribute and synthesizing them, you should always release the objects their ivars point to.
I think Use of properties by Xcode 4 templates will explain this better and more in detail than I could.
I have the following code for a property whose getter/setter I write manually using the #dynamic keyword:
#property (nonatomic, retain) NSObject* obj;
#dynamic obj;
-(NSObject*) obj
{
return obj;
}
-(void) setObj:(NSObject*)newObj
{
[obj release];
obj = [newObj retain];
}
My question is, if I remove the retain from the #property declaration, the compiler complains that the default will be assign and that it may not be what I want. If I add the retain, I assume it is going to be ignored, because I wrote the getters/setters myself?
Just looking for a quick confirmation on this.
You are correct, but your property declaration is as much for documentation as it is for your implementation, at least in this case. At some point, someone (you in six months?) will look at your .h file and say, "Why isn't this value being retained? How does this not crash every time it gets run or leak memory like a sieve?"
The retain allows your object to stay allocated in memory until you apply
[obj release];
so even if you do have your own setter and getter you need to keep the retain to keep your place in memory, because in the end you only have a pointer to that position and that is why the compiler tels you that you may modifying another object or what ever takes the place of your object.
And its important that you make the release to free the memory when you are done using it.