Strange variable allocation in iOS book - iphone

I have spotted an example in book: "iOS4 Programming Cookbook" that I can't understand:
Tray *newTray = [[Tray alloc] initWithPrinter:self];
paperTray = [newTray retain];
[newTray release];
I can't understand why we need a newTray variable. Why we couldn't just use this code:
paperTray = [[Tray alloc] initWithPrinter:self];
Tray is just a Model Class. paperTray - property: Tray *paperTray;

You don't need the newTray variable at all. The alternate code you posted would be equivalent, and less verbose.
The author may have included the other variable just to make it clear precisely what [[Tray alloc] initWithPrinter:self] does.

The author was probably copying a very common pattern that actually makes sense when you're dealing with properties:
Tray *newTray = [[Tray alloc] initWithPrinter:self];
self.paperTray = newTray;
[newTray release];
Now this is very different! If paperTray is a property that was declared with (retain) (and most properties are) then the second line will actually call a setter that retains the given object again. The above three lines are still excessive, but are actually a common pattern that you'll see in a lot of code (including some Apple's example code, iirc). The other variable makes it clear that you're balancing the initial alloc with a release, since the property secretly retains it again.
You could write this more concisely like this:
self.paperTray = [[Tray alloc] initWithPrinter:self];
[self.paperTray release];
or even
self.paperTray = [[[Tray alloc] initWithPrinter:self] autorelease];
but these don't really save you much effort, and are probably more, not less, confusing if you don't know how properties work. So I usually use the three-line pattern that introduces an extra variable. It's idiomatic.
Again, though, this only makes sense with retained properties. In the code in your post, there is no reason whatsoever to use an extra variable. Either the author was using the pattern without understanding its purpose, or initially was using properties and then changed it without much thought.

Related

Using properties immiedatly or use temporary variables while configuring?

If I have a property like this:
#property (nonatomic, retain) UILabel* lblUsername;
Should I in viewDidLoad do this:
self.lblUsername = [[[UILabel alloc] init...] autorelease];
self.lblUsername.text = #"A label";
self.lblUsername....
Or should I do this:
UILabel* usernameLabel = [[UILabel alloc] init...];
usernameLabel.text = #"A label";
usernameLabel....
self.lblUsername = usernameLabel;
[usernameLabel release];
I have seen both and I am unsure which I should use, any benefits of using one over another? (I know both are "correct" in syntax and both work, but which is preferred?)
I prefer the second method. The only real benefit is reducing stress on the autorelease pool, which is minimal if only initializing a few objects like this. It's unlikely that you are modifying that property on another thread that could potentially cause unintended behavior if using the first method, but I suppose that is a risk. To me it also seems to be the difference of building a component and then installing it versus installing an unfinished component then building it in place.
I'd go for the second one every time. Besides the important fact that it makes little sense to stick half-constructed objects in your public interface (even if you don't yet have a codepath that could expose the bug), the second way is more efficient with zero cost. For every self.thing.otherThing =, you're sending a minimum of two messages, and more if you someday get KVO involved. There is absolutely no benefit to that indirection — it doesn't make your code read more clearly, it doesn't make it more concise, it doesn't make it safer, nothing.

should I always use self.classvariable?

When coding my iPhone app. Is it always a good practice when setting or getting values to use self? I seem to forget half of the time and recently have been tracking down a bug I believe is related to this.
Should I ALWAYS use self or are there cases when it's not necessary or would cause problems?
Edit:
Here's an example of what I'm doing in the code
else if([CellIdentifier isEqualToString:#"Linked Item"]) {
linkedItemLabel = [[UILabel alloc] initWithFrame:CGRectMake(120, 5, 160, 34)];
linkedItemLabel.adjustsFontSizeToFitWidth = YES;
linkedItemLabel.textColor = [UIColor blackColor];
linkedItemLabel.font = [UIFont systemFontOfSize:17.0];
linkedItemLabel.text = [storedValuesMutableArray objectAtIndex:7];
linkedItemLabel.backgroundColor = [UIColor clearColor];
linkedItemLabel.textAlignment = UITextAlignmentRight;
[cell addSubview:linkedItemLabel];}
This is part of the code that sets up my tableviewcells for a form that needs to be filled. Should I be using self.linkedItemLabel or is this fine?
You have to understand that using self.property is a method call (getter or setter method), not a simple assignment.
You should use the ivar directly only inside the setter or getter body.
Reasons:
1/ Properties are meant to shield you from the retain-release hell. Let's imagine you have a "assign" property, you are using the ivar directly and then you decide changing it to "retain". What you get is a bug difficult to find.
2/ Setters and getters can do additional functionality (e.g. setter can add/remove observers to an object) or logging. If you are using the ivar directly you miss this special functionality.
3/ Setters and getters can be overriden in a subclass.
In small projects you can probably avoid most problems even if you are using ivars directly but on big projects, programmed by a team, you should use only self.property to reduce bugs and improve code maintainability.
It's also a good idea to give your ivar a different name (like property_ or _property because you'll notice when you are using it without self..
If you are not writing a high performance game or mathematic algorithms, don't worry about worse performance when using self.property.
It depends on the case, if you are just using #synthesize to auto-generate the getters, then it would not cause any problems on the getters. Although common OO practices tell you to use encapsulation, you will notice pretty much all apple sample code accesses the ivar directly.
Another common practice to refer to the ivar without using self is to synthesize like this:
#synthesize myVar=_myVar
and use _myVar when referring to that variable.
It would only cause a problem, if you implemented something in your getter, instead of using #synthesize.
As for the setters, it isn't exactly a problem, but you just have to keep in mind that the properties for that ivar will only be applied if you do self.myIvar as opposed to accessing the iVar directly, so for example a property declared as (retain), will only be retained if you do self.myIvar = newValue as opposed to myIvar = newValue.
The issue arises with properties. if you do not add the self., then you end up assigning to the variable directly, missing out on the property attributes e.g. retain, assign and thus messing up reference counting for the item, and thus causing potential memory leaks.
You should use self, unless you have an explicit reason not to.
You must use it with clever and clear understanding.
If you're using so-called dot-syntax (i.e. self.myVariable) it means you're calling a getter or setter of the property, which is actually a selector sending to an object instance, which is pretty heavy within Objective-C run-time. So, if you need just a value of your var - you can call it once and reuse saved state or call directly to i-var (if permissions allow).
Call for getters/setters when you really need them.

iPhone: When to make an Objective C variable an instance variable?

Generally speaking, when should you make a variable in Objective C an instance variable?
For instance, say I got an UIViewController with an UILabel. In what cases would I have the UILabel as an instance variable vs doing something like this:
UILabel *label = [[UILabel alloc] init];
//set text of label
[view.addSubview label];
[label release];
If you need a moderately persistent handle on any resource, you should make it an instance variable, if the resource in question should remain at least moderately persistent.
In the example above, then yes; the label should be an instance variable, probably one assigned using an IBOutlet.
Generally speaking, most things that live in UIKit (as opposed to Foundation) benefit from being instantiated through NIB files and subsequently accessed through outlets.
This isn't solely a performance issue; it also has to do with memory management and fragmentation, as well as simplifying, in most cases, translation and internationalization.
To your specific case, if you are going to need to access that label at a later point in time (say to change the text) keeping an ivar will save you some effort trying to find it again.
General reasons would be for persistence, scope, and convenience.
In your particular example, the object is written as a variable so that it can be sent a release message after adding it to a view (which retains it).
The equivalent code without a variable is:
[view addSubview:[[[UILabel alloc] init] autorelease]];
We don't need to send a release, because we're autoreleasing the object.

Why do people always use reassignment for instance variables in Objective-C (namely iPhone)?

I always see example code where in the viewDidLoad method, instead of saying, for example
someInstanceVar = [[Classname alloc] init];
they always go
Classname *tempVar = [[Classname alloc] init];
someInstanceVar = tempVar;
[tempVar release];
Why is this? Isn't it the exact same thing, just longer?
The short answer: This pattern shows up all the time in iPhone code because it is considered the best way to create a new object and assign it to a member variable while still respecting all of the memory management rules and invoking the appropriate side effects (if any) while also avoiding the use of autorelease.
Details:
Your second example would create a zombie, since var is left holding a pointer to memory that has been released. A more likely usage case looks like this:
tempVar = [[Classname alloc] init];
self.propertyVar = tempVar;
[tempVar release];
Assuming that propertyVar is a declared as copy or retain property, this code hands off ownership of the new object to the class.
Update 1: The following code is equivalent, but not recommended* on iOS, which is probably why most iPhone programs use the first pattern instead.
self.propertyVar = [[[Classname alloc] init] autorelease];
* autorelease is discouraged on iOS because it can cause problems when overused. The easiest way to be sure you never overuse it is to never use it all, so you will quite often see iOS code that uses alloc/init and release, even when autorelease would be acceptable. This is a matter of coder preference.
Update 2: This pattern looks confusing at first because of the memory management that Cocoa performs automagically behind the scenes. The key to it all is the dot notation used to set the member variable. To help illustrate, consider that the following two lines of code are identical:
self.propertyVar = value;
[self setPropertyVar:value];
When you use the dot notation, Cocoa will invoke the property accessor for the indicated member variable. If that property has been defined as a copy or retain property (and that is the only way for this pattern to work without creating a zombie), then several very important things happen:
Whatever value was previously stored in propertyVar is released
The new value is retained or copied
Any side effects (KVC/KVO notifications, for example) are automatically handled

Use autorelease before adding objects to a collection?

I have been looking through the questions asked on StackOverflow, but there are so many about memory management in Objective-C that I couldn't find the answer I was looking for.
The question is if it is ok (and recommnded) to call autorelease before adding a newly created object to a collection (like NSMutableArray)? Or should I release it explicitly after adding it. (I know NSMutableArray willl retain the object)
This illustrates my question:
Scenario A (autorelease):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
}
Scenario B (explicit release):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
[obj release];
}
I assume both are correct, but I am not sure, and I sure don't know what the preffered way is.
Can the Objective-C gurus shed some light on this?
IMHO, which way is 'right' is a matter of preference. I don't disagree with the responders who advocate not using autorelease, but my preference is to use autorelease unless there is an overwhelmingly compelling reason not to. I'll list my reasons and you can decide whether or not their appropriate to your style of programming.
As Chuck pointed out, there is a semi-urban legend that there's some kind of overhead to using autorelease pools. This could not be further from the truth, and this comes from countless hours spent using Shark.app to squeeze the last bit of performance out of code. Trying to optimize for this is deep in to "premature optimization" territory. If, and only if, Shark.app gives you hard data that this might be a problem should you even consider looking in to it.
As others pointed out, an autoreleased object is "released at some later point". This means they linger around, taking up memory, until that "later point" rolls around. For "most" cases, this is at the bottom of an event processing pass before the run loop sleeps until the next event (timer, user clicking something, etc).
Occasionally, though, you will need to get rid of those temporary objects sooner, rather than later. For example, you need to process a huge, multi-megabyte file, or tens of thousands of rows from a database. When this happens, you'll need to place a NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; at a well chosen point, followed by a [pool release]; at the bottom. This almost always happens in some kind of "loop batch processing", so it's usually at the start and bottom of some critical loop. Again, this should be evidence based, not hunch based. Instrument.app's ObjectAlloc is what you use to find these trouble spots.
The main reason why I prefer autorelease to release, though, is that it is much easier to write leak-free programs. In short, if you choose to go the release route, you need to guarantee that release is eventually sent to obj, under all circumstances. While this seems like it might be simple, it is actually surprisingly hard to do in practice. Take your example, for instance:
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
// Assume a few more lines of work....
[obj release];
Now imagine that for some reason, something, somewhere, subtly violates your assumption that array is mutable, maybe as the result of using some method to process the results, and the returned array containing the processed results was created as a NSArray. When you send addObject: to that immutable NSArray, an exception will be thrown, and you will never send obj its release message. Or maybe something goes wrong somewhere between when obj was allocd and the required call to release, like you check some condition and return() immediately by mistake because it slipped your mind that that call to release later on must take place.
You have just leaked an object. And probably signed yourself up to several days of trying to find out where and why it is your leaking it. From experience, you will spend many hours looking at that code above, convinced that it could not possibly be the source of the leak because you very clearly send obj a release. Then, after several days, you will experience what can only be described as a religious epiphany as you are enlightened to the cause of the problem.
Consider the autorelease case:
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
// Assume a few more lines of work....
Now, it no longer matters what happens because it's virtually impossible to leak obj accidentally, even under extremely unusual or exceptional corner cases.
Both are correct and will work as you're expecting them to.
I personally prefer to use the latter method, but only because I like to be explicit about when objects get released. By autoreleasing the object, all we're doing is saying "this object will get released at some arbitrary point in the future." That means you can put the autoreleased object into the array, destroy the array, and the object might (probably) still exist.
With the latter method, the object would get destroyed immediately with the array (providing that nothing else has come along and retained it in the meantime). If I'm in a memory-constrained environment (say, the iPhone) where I need to be careful about how much memory I'm using, I'll use the latter method just so I don't have so many objects lingering in an NSAutoreleasePool somewhere. If memory usage isn't a big concern for you (and it usually isn't for me, either), then either method is totally acceptable.
They are both correct but B may be preferred because it has no overhead at all. Autorelease causes the autorelease pool to take charge of the object. This has a very slight overhead which, of course, gets multiplied by the number of objects involved.
So with one object A and B are more or less the same but definitely don't use A in scenarios with lots of objects to add to the array.
In different situations autoreleasing may delay and accumulate the freeing of many objects at the end of the thread. This may be sub-optimal. Take care that anyway autoreleasing happens a lot without explicit intervention. For example many getters are implemented this way:
return [[myObject retain] autorelease];
so whenever you call the getter you add an object to the autorelease pool.
You can send the autorelease message at any point, because it isn't acted on until the application's message loop repeats (i.e. until all your methods have finished executing in response to user input).
http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text
You have alloc'ed the object, then it's your job to release it at some point. Both code snippets work merely the same, correct way, with the autorelease way being the potentionally slower counterpart.
Personally speaking, I prefer the autorelease way, since it's just easier to type and almost never is a bottleneck.
They're both OK. Some people will tell you to avoid autorelease because of "overhead" or some such thing, but the truth is, there is practically no overhead. Go ahead and benchmark it and try to find the "overhead." The only reason you'd avoid it is in a memory-starved situation like on the iPhone. On OS X, you have practically unlimited memory, so it isn't going to make much of a difference. Just use whichever is most convenient for you.
I prefer A (autoreleasing) for brevity and "safety", as johne calls it. It simplifies my code, and I've never run into problems with it.
That is, until today: I had a problem with autoreleasing a block before adding it to an array. See my stackoverflow question:
[myArray addObject:[[objcBlock copy] autorelease]] crashes on dealloc'ing the array (Update: Turns out the problem was elsewhere in my code, but still, there was a subtle difference in behavior with autorelease…)