Property does not seem to be used? - iphone

This is something that I came across in the Apple reference material - Sample Code when researching how to use NSTimer, I am not asking about NSTimer as thats a seperate question but I am curious about the use of the #property, the direct assignment to the iVar (i.e. not using the property setter) and the subsequent release.
#property (nonatomic, retain) NSTimer *updateTimer;
...
#synthesize updateTimer;
...
updateTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(updateCurrentTime) userInfo:p repeats:YES];
...
...
updateTimer = nil;
...
...
// Dealloc method
[updateTimer release];
My question is, does the property get used at all, it seems not? Also the release, does that work, where is the retain if the #property setter is not being used?

The retain is in the definition of the property. (i.e. where it says "(nonatomic, retain)" in brackets.)
If the property had been allocated, it would be retained "automatically" by the setter it at that time.
But just as you say the property itself is never used, so it is never allocated or retained.
The release you can see in the code appears to be simply wrong, just as you say. The ivar was never retained so a release would crash just as Bjorn pointed out.
(Note that they apparently set it to nil -- of course you can send any message at all to nil, but just as you say it's a really silly example. You can't release something you never retained.)
Exactly as you say, the example is a little weird. There was "no reason" to make a property: just as you say it was never used. Conversely, why did they release the ivar - which was never retained.
So in short your suspicions seem to be correct!
There are at least three horrible errors in that code!

You are right, the property is never used as there is no call like self.updateTimer = something or [self setUpdateTimer:something]. Sending the release message in -dealloc "works" because you reset updateTimer to nil. It is perfectly fine to send messages to nil, but nothing is going to happen. If you did not reset the variable to nil, the message would have been sent to a deallocated instance and cause an EXC_BAD_ACCESS exception.

If you use a dot, the property method gets called. Otherwise it is simple assignment. For instance, foo = bar would be assignment, whereas self.foo = bar would result in the property method getting called.
Try using self.updateTimer = ....

Related

Releasing a (nonatomic, retain) synthetized property

My question looks like a dozen ones about releasing properties, but I can't find the exact answer i'm searching for.
When a property is declared with retain :
#property (nonatomic, retain) NSString * myString;
then
#synthesize myString;
It generates getters and setters with retaining and releasing operations. Okay.
Of course, property must be released in dealloc.
-(void)dealloc {
[myString release];
myString = nil;
[super dealloc];
}
So that's clean.
But what if i never use myString ? Is it pre-initialised ? My opinion is the myString retain-count would be 0. But releasing myString in dealloc would decrease it and make the application crash ? But it does not crash !
Is a cleaner way to release it like ?
if(myString != nil) {
[myString release];
myString = nil;
}
The key thing you are missing is that you can send messages to nil. So no, your latter approach is not cleaner, just unnecessary.
If you never use myString, it's not initialized to anything. It remains nil. When you release it, you are effectively doing [nil release] - which doesn't actually do anything. Hence no crash.
There is no need to check wether it is nil.
If you send the release to a nil object nothing happens, so why check.
When an instance of object is created the property will be set to nil unless you initialize it in any of the init methods.
It not the same with variables you create in a method, they could point to invalid memory. Thus setting these to nil is the safe way. This is not needed for properties.
You can send release messages to nil objects in objective-c this way nothing happens. I mean the application wont crash. The idea behind setting objects to nil comes handy when an object is used in multithreaded environment since with multiple threads you can't always guarantee that an instance variable will only be read before it's released.
if you are using #property(retain/copy) & #synthesize there is no need to check for nil. It won't crash or throw EXC_BAD_ACCESS.
Otherwise, if you are not using that, you have to check whether the variable is nil or not, or it will crash if the variable is nil.

Impact of releasing a variable more then the retain count

I have a instance variable declared as a retain property & then I released it 2 times. After releasing it I am not using it. This is not resulting into any crash. Is there any other impact of releasing a variable more than required (given that the variable is not going to be used after the release):
#property (nonatomic, retain) NSString *myVariable;
self.myVariable = nil;
self.myVariable = nil;
You are not, in fact, releasing it twice. This is because you're using properties. The first time you call self.myVariable = nil, you're releasing it (assuming it had a value). But the second time, it's already nil, so there's nothing to release.
In general, actually releasing an object multiple times (or more accurately, having more releases than retains) is really bad and will almost certainly crash your app.
You're not actually releasing it twice. Given that the setter looks something like this:
- (void)setMyVariable:(NSString)value
{
[myVariable release];
myVariable = [value retain];
}
The first self.myVariable = nil will release the myVariable iVar, and will also set it to nil. The next self.myVariable = nil will do nothing, because [nil release] does nothing.
Actually overreleasing an object will (usually) cause a crash.
You might be confused about the difference between a variable and an object. A single variable can be used with a release an infinite number of times (say, if is nil, or it holds a completely different retained object before each release, etc. This is because a variable can hold no object, or different objects at different times.). In your example, the variable holds no object (nil) during your second release.
But releasing any one non-nil object just one time too many can be the cause of a crash.
With the new ARC (Automatic Reference Counting) in iOS 5 you shouldn't worry about this issue, since the compiler takes care of this.
Learn more about it here:
http://clang.llvm.org/docs/AutomaticReferenceCounting.html
However, if you can't / don't want to use ARC, here is my alternative answer:
By accessing your vars the way you are doing ( self.var = nil ), my guess is that these synthesized functions take care of not releasing a non-retained var, so you are safe to do so as many times you like (not very elegant though).
If, on the other hand, you would explicitly call release like this [var release] twice or more, you might run into pretty nasty problems.
Nothing will happen in your code. I assume you are using ARC (Automatic Reference Counting) so you are "releasing" it by setting its pointer to nil.
How it really works is, suppose you have a NSString object allocated in memory, you create it and you assign a pointer to it.
So now your pointer is pointing to that object, what arc does is: If an object no longer has a pointer pointing to it then it is automatically released. Assuming you had ONLY that "myvariable" pointer on that NSString then it will be released the moment you set it to nil.
If you set the myvariable to nil again then you are absolutely not doing anything to it since the object was already released before.
Note that this means that if you have ANOTHER variable also pointing to that NSString then the object WONT be released but myvariable wont be pointing to it anymore.
I forgot to mention, you can find an excellent explanation about how arc works in "iOS 5 by tutorials" by Ray Wenderlich.
PD: If you are using ARC u should change your
#property (nonatomic, retain) NSString *myVariable;
to
#property (nonatomic, strong) NSString *myVariable;

Require some understanding for Singleton Pattern

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.

Objective-C (iPhone) ivars and memory management

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.

objc_msgSend() error message, why?

I got the "objc_msgSend()" killer error message in my app and thanks to Hamster Emporium
i can figure out a little bit what was happening.
Now i found the "problem" and the "solution", but what i can't understand why my problem was really a problem.
Here is the scenario:
Object_A --> Object_B --> Object_C
The '-->' symbol represent the "create" action.
Class of Object_C looks like this:
#interface Class_C {
NSArray *items;
}
#property (nonatomic, retain) NSArray *tems;
#end
The property 'items' is set in Object_B through a 'setItems' method:
- (void)setItems:(NSArray *)items_ {
if (object_B) {
[object_B.taskItems release];
object_B.taskItems = items_;
}
[super setItems:items_];
}
Now, if I use this method as is I got the blasphemous 'objc_msgSend()' error BUT if I comment the release line everything goes well.
Note: the retainCount in the release line is 0, but the release execute without problems
You are getting that error because the taskItems member variable is being released twice. There is no need to manually release taskItems because using the dot syntax takes care of it automatically.
This line:
object_B.taskItems = items;
Invokes the property accessor for taskItems, in which the old value is automatically released before the new one is retained (or copied, depending on the property definition).
A very good general rule for Cocoa memory management is that you should only release an object if you created it (either by alloc/init or by copy). Releasing object_B.taskItems would violate that rule.
Uhm, wow. ok.
object_B.taskItems = items_;
is the same as calling
[object_B setTastItems: items_];
if taskItems is a property set to retain, you don't need to release it first since the property will do so. The way you have your code right now, it gets released twice.
Remember, properties are not the same as members in Objective-C. Properties are methods which access the private members of the class (and do fancy stuff like retain/release and #synchronized).
I had a similar problem, but in my case this was the scenario:
I made a controller that registers itself to listen for changes in a NSOperation attribute "isFinished", while the NSOperation was working my controller went away, when the NSOperation finished and tried to notify:
[self willChangeValueForKey:#"isFinished"];
I got
objc_msgSend() corrupt cache error
But it was because my Controller was out of scope, to fix it I wait for the results of NSOperation KVO and then move to next controller.