I have a property that has (nonatomic, assign) as attributes.
In a method, I then am retaining that variable then releasing it a line after.
Static analyzer is giving warning that incorrect decrement of the reference count of object....
Can I not do this
#property (nonatomic, assign) Class *iVar;
[self.iVar retain];
[self.iVar removeFromSuperview];
[self insertSubview:self.iVar atIndex:self.iVar.index];
[self.iVar release];
Since the retain and release both happen in the same method, you might want to copy the property to a local variable and then work with that:
UIView *someView = self.interestingView;
[someView retain];
//...do some stuff...
[someView release];
That at least provides some protection in case the "some stuff" part happens to modify self.interestingView. And it'll probably satisfy the static analyzer, too.
In general, I would avoid retaining/releasing variables that back properties outside the accessors for those properties, except for a few well defined situations such as -dealloc. Similarly, avoid directly retaining/releasing the result of a property access, as in [self.foo retain]. If that property is changed before you get to the release, you end up with both a leak and, later, an over-release.
The trouble is that you're not working with a variable; you're working with the result of a property accessor. Each time you access the property, the static analyzer applies the normal memory management rules for an object returned from a method — namely, you shouldn't be releasing it. If you change it to use an actual local or instance variable, the warning will go away.
I just tested a similar example,
You will appease the static analyzer by not using property notation
[iVar retain];
[self.iVar removeFromSuperview];
[self insertSubview:self.iVar atIndex:self.iVar.index];
[iVar release];
Or you could use a temporary variable.
Related
Suppose I have this code...
foo.h
#interface Foo : NSObject {
NSString *aString; // 1
}
#property (nonatomic, retain) NSString *aString;
foo.m
#synthesize aString = _aString;
....
- (void)dealloc {
[aString release];
[super dealloc];
}
My questions are:
do I really need to declare aString in "1"? (see code)
if I am synthesizing aString = _aString, I am already creating an instance
variable, right?
if I am retaining the property on foo.h (#property), why Xcode complains if I release aString in dealloc?
thanks.
You are mixing up the property and the backing variable. "aString" is the property, which you access via method call (e.g. [self aString]). "_aString" is the backing variable, which you access directly (e.g. _aString).
Taking your questions in order:
No. This is an unused variable because you told the compiler to use _aString as the variable. (You don't actually need to declare either one in the modern run-time.)
Yes, as indicated in my answer to the first question.
Because the compiler expects you to send a message to an object, and "aString" is undefined as written. Normally you would use [self aString] to access the object, but this is a special case: in -dealloc and in -initXYZ you don't use accessor methods because of potential side effects. Switch to [_aString release] and everything will work (unless you have ARC, in which case you don't release at all.
With your #synthesize, the instance variable (your "1") should be NSString* _aString.
The reason you use synthesize with a differently named variable is so that you always use self.aString to properly release the old object instead of accidentally overwriting the pointer by directly modifying aString.
Do you have ARC enabled? If so, that's why Xcode complains about releasing it.
To answer your questions in order:
No. There might some sort of "best-practice" reason that I'm missing, but #property will synthesize the instance variable as well.
When you declare aString = _aString, what that allows you to do is directly manipulate _aString without accessing the synthesized getter/setter (by calling _aString) or use the synthesized getter/setters (by calling self.aString).
You are likely releasing it somewhere else, someone else is over-releasing it, or you're using ARC. With NSStrings (and other simple objects that have deep copy method readily available), I find it best to use #property (copy), and _aString = [stringPassedToInit copy], so that you are the only one handling your string's retain count. If you're using ARC, you don't need to worry about retain/release in most instances.
No, you don't need to declare ivars any more (since iOS 3 I think). You can delete the entire { ... } part of your interface declaration and it won't make any difference.
It's complaining because your ivar is named _aString, not aString. You need to say
[_aString release]
instead.
Answers : -
do I really need to declare aString in "1"? (see code) - Now with iOS 4 onwards you won't need to declare.
if I am synthesizing aString = _aString, I am already creating an instance variable, right? - Yes
if I am retaining the property on foo.h (#property), why Xcode complains if I release aString in dealloc? - now you need to use this - self.aString = nil, this will take care.
My answers are:
NO
YES
Try [_string release] instead.
I am going to paste a code here and had a question regarding that which I wanted to understand merely, based on the logical way.
#interface MySingleton : NSObject {
NSString *enteredCode;
}
#property (nonatomic, retain) NSString *enteredCode;
#end
#synthesize enteredCode;
-(void) addInput:(NSString *) input
{
self.enteredCode = [self.enteredCode stringByAppendingString:input];
}
- (void)dealloc {
[enteredCode release];
}
#end
In my code, if I utilize "self.enteredCode = [self.enteredCode stringByAppendingString:input];"
everything works fine but "enteredCode = [self.enteredCode stringByAppendingString:input];" it gets exc_bad_access, and I am just wondering why this case be?
I am just trying to understand what difference really does it makes without having self there?
Thanks.
This is not to do with singletons. When you do self.enteredCode you are going through the property which is set to 'retain'. The stringByAppendingString method is a convenience method with returns an autoreleased object to you, meaning that it will be released at some point on the next run loop. You need to retain this value to stop it being released, which is fine when you assign it through the property as it is properly retained by you and you can use it as you like.
When you reference the variable directory (without the self.) you bypass this and as such you don't ever retain the value, the value is subsequently released and you reference bad memory and BOOOOOOOOM, bad access.
when you call self.enteredCode = XXX it will call [self setEnteredCode:XXX]. Since you are using a retain property this will release the old value of enteredCode, and retain the new value.
if you directly manipulate the enteredCode variable you will have memleaks and crashes because it will try to release something that is not retained later.
If I understand correctly, self.enteredCode works but enteredCode fails.
If that's the case then I believe it's because you're bypassing the property and setting the iVar directly. That means you're assigned an auto released object and bypassing the retain mechanism.
Consider using something like _enteredCode for your iVars do it's clearer in your code when you're bypassing properties.
I'm certain that I'm missing some fundamental understanding of iOS memory management and, despite lots of reading and searching, I'm still not getting it.
I use a singleton in my app that has info about the user currently signed into it, info accessed from multiple view controllers, etc. It has multiple ivars that are get and set throughout the app. They're declared and propertied in the .h file like so:
NSString *myString;
and are made retained like so:
#property (non atomic, retain) NSString *myString;
and synththesized in the implementation.
I get and set their values in methods in the singleton like this:
myString = #"value";
and
methodLocalString = myString;
In other places I include the singleton -- call it CurrentUser -- I import it:
#import "CurrentUser.h"
Outside of the singleton I get and set it like this:
[CurrentUser sharedCurrentUser].myString = #"Bob";
and
myOutsideString = [CurrentUser sharedCurrentUser].myString;
Most of the time this works great, with the values appropriately persisted from one getting or setting to another. The trouble is that sometimes when I get them that way I find that they've been released (crashing the app), which NSZombieEnabled thankfully tells me.
What I don't get is how his can happen. I thought the singleton was never released, and that therefor retained properties of the singleton would never be released. I'll note that the problem seems to be more common with non-real-object properties like NSDate and definitely-not-object properties like int and BOOL which can't be retained, but it happens with object properties as well.
What am I ignorant about here? And thanks for your patience.
Your problem is:
I get and set their values in methods
in the singleton like this:
myString = #"value";
When you assign directly to the iVar, instead of using the property syntax (self.myString = #"value"), you are bypassing the synthesized setter method, which means that the retain never happens.
Properties aren't magic. They're just a bit of syntactic sugar for the "." access, and the ability to have synthesized getter/setter methods to save you the tedium of writing your own.
self.myString = #"value";
is just shorthand for
[self setMyString:#"value"];
The synthesized setMyString method will do something like:
if (myString != newValue) {
[myString release];
myString = [newValue retain];
}
(assuming retain option on the #synthesize)
Don't use singletons. Your current problem is caused by a simple memory management misconception, but the singleton pattern will only give you more headache in the long run.
I am subclassing NSURLConnection, and used MGTwitterEngine as a base to help me get started. That may be irrelevant. However, I noticed in their code they don't use #property or #synthesize for their ivars. They have wrapped the ivars in accessor methods which look like this:
- (NSString *)identifier {
return [[_identifier retain] autorelease];
}
My question is two part. First, what effect does retain followed by autorelease have? It seems to me it would cancel itself, or worse yet leak.
Second, if I were to change the header file to have:
#property (nonatomic, retain, readonly) NSString* _identifier;
And used #synthesize indentifier = _identifier, wouldn't this do the same thing as the accessor method without having to write it?
Maybe it is just two different ways to do the same thing. But I wanted to ensure I have the correct understanding. Thanks.
Using #synthesize will actually only create a setter and a getter method. The code that is auto generated for you is guaranteed to use proper memory management, so that you do not need to worry.
MGTwitterEngines use of return [[ivar retain] autorelease] is actually the correct way to do it. Lets have two examples.
Assume a getter is defined as this:
-(Foo)foo {
return foo;
}
And then we execute this code:
bar = [[bar alloc] init]; // bar has aretain count of 1.
foo = bar.foo; // foo har a retain count of 1 (owned by bar).
[bar release]; // Bar and all it's ivars are released imidiatetly!
[foo doSomething]; // This will crash since the previous line released foo.
If we instead change the getter to this:
-(Foo)foo {
return [[foo retain] autorelease];
}
bar = [[bar alloc] init]; // bar has a retain count of 1
foo = bar.foo; // foo has a retain count of 2 (one owned by bar, 1 owned by autorelease pool).
[bar release]; // Bar and all it's ivars are released imidiatetly!
[foo doSomething]; // Will not crash since foo is still alive and owned by autorelease pool.
Hope this explains why you should always return properly autoreleased objects from all your getters. It is important that any return value can survive the deallocation of it's parent, since no class ca guarantee what a client will do with it's values once it is exposed to the wild.
Retain followed by autorelease does exactly what you might think it does. It sends the object a retain message and then sends it an autorelease message. Remember that autoreleasing an object adds that object to the autorelease pool but does not release it yet. The autorelease pool will send the object a release message at the end of the current iteration of the run loop. So, a retain followed by autorelease essentially says, "Make sure this object stays around until the end of the the current iteration of the run loop." If you need the returned value to hang around longer, you can retain it. If not, do nothing and the autorelease pool will handle it.
In this case, the string being sent retain and autorelease messages is a property. It's already retained by the parent object. So you might wonder why do this retain and autorelease thing at all? Well, there's no guarantee that the object won't release _identifier before the current iteration of the run loop ends. Consider this example:
- (NSString *)identifier { return _identifier; }
- (void)aMethod {
NSString *localId = [self identifier]; // localId refers to _identifier which is only retained by self
[self methodThatChangesIdentifierAndReleasesItsOldValue]; // self releases _identifier
NSLog(#"%#", localId); // crash, because localId (old value of _identifier) has been released
}
In this case, the returned identifier isn't retained and autoreleased. The NSLog line crashes because localId refers to a released string. However, had we used retain and autorelease in the getter, there would be no crash because localId would not be released until the end of the current iteration of the run loop.
As far as I know, your replacement with an identifier property would be just as good. It might not be identical code, but the effect should be the same.
Apple explains this well in Implementing Accessor Methods. The method quoted by you (named "Technique 1" by Apple) helps avoid bugs if the caller assigns a new value to the identifier property and then expects the retrieved value to still be available. It won't be needed most of the time but just returning the ivar value can lead to bugs that are hard to track down.
Generally one retains then autoreleases if you are returning something that you didn't own the first place. It will only leak if you own _identifier and there is a mismatch of retain/alloc/etc versus release/autorelease sent to that object.
Secondly, yeah you generally don't have to write the headers if you aren't doing something special beyond what the general boilerplate looks like. Apple has good documentation on properties, I suggest if you're still fuzzy, you look at those.
I was looking at some sample code on Jeff LaMarche's excellent blog when I came across the following:
- (void)applicationDidFinishLaunching:(UIApplication*)application
{
CGRect rect = [[UIScreen mainScreen] bounds];
window = [[UIWindow alloc] initWithFrame:rect];
GLViewController *theController = [[GLViewController alloc] init];
self.controller = theController;
[theController release];
// ...
}
In the .h, we see that "window" and "controller" are ivars declared as so:
#interface OpenGLTestAppDelegate : NSObject
{
UIWindow *window;
GLViewController *controller;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet GLViewController *controller;
#end
My question is: Why are "window" and "controller" assigned in different ways?
I think I understand why each kind of assignment works (keeping track of retain count), but why are they assigned in different ways? Specifically, why isn't controller assigned in the same way window is with a single line like so without going through the setter:
controller = [[GLViewController alloc] init];
In general, when would you use the single line method and when would you use the multiple line method?
Thanks.
Does he create a custom setter for the controller instance variable?
If so, there may be code which is called when the controller variable is changed through the setter. Merely setting the controller variable with:
controller = [[GLViewController alloc] init];
would not invoke the setter method; however, assigning the newly allocated object to a local variable then setting it with:
self.controller = theController;
would invoke the setter method since it is a shorthand way of writing:
[self setController:theController];
and the extra code in the setter would be executed. This is commonly where you would expect the differentiation between the two methods.
Edit:
Evidently, after taking a look at the code, he doesn't implement a custom setter method, however the method that he has used is still most commonly used when a custom setter method would be implemented.
My guess at the reason behind the extra code would be that he plans to release the variable after allocation, and if assigned to a local variable, he can call the setter method with the local variable and then call release on the local variable afterwards. This would be overall more readable than using
[[self controller] release]
However, it is an odd way to do it, as the synthesized implementation of the setter will retain the instance variable, yet he then releases it once it has been set to the instance variable, and as the release call cancels out the retain call, it would make more sense to set the variable using the one-line method.
The extra code seems to be just because he specifically wants to use the property (setter method). In his implementation (GLView.m), -setController also sets a boolean ivar based on whether the controller responds to (implements) the -setupView: method.
Even so, it would seem that a one-line solution would work just as well:
self.controller = [[[GLViewController alloc] init] autorelease];
The same line as an explicit message send (without dot syntax) works as well:
[self setController:[[[GLViewController alloc] init] autorelease]];
Either approach will leave the new controller with the proper retain count, and still uses the setter property as desired.
(Note: The code in question is linked at the end of this blog post.)
Edit:
Sorry for any confusion. The code has a "GLViewController *controller" ivar and property both in ___PROJECTNAMEASIDENTIFIER___AppDelegate.m and GLView.m, and I was looking at the latter. (In the former, the setter is indeed synthesized, and it will retain the controller. On lines 77-81, you can see the code I mentioned, and he doesn't actually retain the controller — only the AppDelegate retains it.)
In the app delegate code, the synthesized setter will retain the GLViewController, so my one-line replacement advice still stands. One can argue both ways about readability, but for those who understand the retain-release idiom well, I would suggest that the one-line version is much more readable. It communicates the intent succinctly, and even provides an implicit hint that the setter will retain the controller. The extra local variable is really just unnecessary fluff.
As Quinn pointed out, the assignment to the controller ivar may be written in one line using autorelease method. The reason to use more verbose version is exactly to avoid autorelease and use manual release instead. This is due to Apple recommendation to minimize the use of autorelease pools on iPhone. So you must store the reference to the newly allocated object in a local variable to release it after a call to setter.
Considering the question when to use direct assignment to an instance variable (as in the case of window ivar) and when to use a setter method (as in the case of controller ivar), it is mostly a question of style, but you better be consistent.
There are two styles of ivar setting:
Always use direct assignment to an ivar. Switch to setter methods only for ivars for which setter must perform some additional work beside assignment.
Always use setter methods for all ivars.
Personally, I think that use of the second style results in more consistent and maintainable code. If some day you realize that your setter must perform more work you should change only the setter, while when using the first style you also should change all occurrences of direct assignment to the setter call.
Just found the good discussion of the issue in another thread: instance variable/ method argument naming in Objective C.