Using properties immiedatly or use temporary variables while configuring? - iphone

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.

Related

Why create a variable rather than direct assignment?

This is a basic question, and I'm not really sure what to search for to see if its been asked before.
In a lot of examples, I've seen property assignments handled like this:
NSArray *tempArray = [/*some code to get array*/];
self.propertyArray = tempArray;
[tempArray release];
Why not just do:
self.propertyArray = [/*some code to get array*/];
What's the difference between the two?
This answer is assuming your not using ARC.
The first code snippet, is the way Apple recommends initializing a property as long as you are doing this in any method besides init. You'll notice Apple code snippets do this a lot. It makes it much easier to manage your memory, and in my opinion it makes it easier to read.
NSArray *tempArray = [[NSArray alloc] initWith....]
self.propertyArray = tempArray;
[tempArray release];
The second code snippet you have could potential lead to a memory leak depending how you set up the NSArray.
This would be a leak. The propertyArray would have an retain count of 2. After you release the instance variable in dealloc, you still have a retain count of 1. That is a leak.
self.propertyArray = [[NSArray alloc] initWith...];
This would be okay, because they both are being autoreleased, which would give you a retain count of 1. As, long as you release the instance variable in dealloc.
// Class Method so autoreleased
self.propertyArray = [NSArray arrayWith....];
// Explicitly declaring autorelease
self.propertyArray = [[[NSArray alloc] initWith.....] autorelease];
It's simply just a matter of preference. I prefer the first way, I think it is easier to to read and follow.
Edit (with ARC):
All these methods would be acceptable with the exception of the release statement and autorelease statement.
[tempArray release];
ARC automatically takes care of the memory management for you, so you do not have to explicitly release them. This is the benefit of ARC, you can create as many objects as you want without the headache of trying to figure out where to release them.
Also, your property would be different. You must either use strong or weak, and not retain. In this case strong would be the solution.
#property (nonatomic, strong) NSArray *tempArray;
In the second example, you don't release the object, which is retained by the property, so you have a memory leak.
self.propertyArray = [[SomeClass alloc] init];
// ^ no release
With ARC, the two statements are equivalent in practice (although you would have to omit the release call for it to actually compile in ARC).
In a manual managed memory scenario, you would leak tempArray in the second ("direct assignment", which it isn't because you're calling a property setter not setting an ivar) example, as you do not have a release call on tempArray to balance it's alloc/init.
The the useful distinction is reduced to expressiveness, the ability to debug, and ultimately the programmers personal preference.
Your first example is the way it was done before the advent of automatic reference counting (ARC). The second example works fine under ARC. Unless you have to do it the old-fashioned way, select ARC for all your projects.
Code like that most likely means that somebody wanted an ability to debug it easier. Basically if you have a separate variable, you can print it out in the debugger without triggering (possibly custom) property setters and getters.

Automatic reference counting confusions

I have been reading different sources for automatic reference counting but haven't found any great article or documentation which clarify my understanding. My understanding about ARC(Automatic Reference Counting) is, it completely takes over developer control on memory management and assign it to compiler to do memory management.
Am I thinking right?
So does that mean retain,release and autorelease is no more for iOS 5 SDK?
Example:
Lets say I use to make object like this,
UIView *message = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, cell.frame.size.width, cell.frame.size.height)];
message.tag = 0;
[message addSubview:balloonView];
[message addSubview:label];
[cell.contentView addSubview:message];
[balloonView release];
[label release];
[message release];
will become like this IF ARC is ON,
UIView *message = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, cell.frame.size.width, cell.frame.size.height)];
message.tag = 0;
[message addSubview:balloonView];
[message addSubview:label];
[cell.contentView addSubview:message];
Any input will be helpful thank you
Cheers!
Yes and no:
Yes, ARC rids you of manually calling retain, release, autorelease, possibly lets you delete quite a few of your dealloc implementations and — on the new runtimes — even introduces zeroing weak references (w00t!), but it does not prevent you from leaking, per se.
It is automated retain/release and not a garbage-collector, so it "allows you" to still leak memory by creating retain-cycles.
Furthermore, it changes the reference semantics of the __block attribute from weak to strong:
Every bit of code where you avoided the capture of self by using __block id blockSelf = self; is now a potential leak — luckily, Clang has become even better warning you about issues like this.
An area, where ARC actually makes you write more code than before, most of the time, is when you are using toll-free-bridging between CFTypeRefs and id <NSObject>s:
The casts have to be annotated to tell ARC what to do or you'll get a compiler error.
If you're working with plain CF APIs, nothing changes: everything stays manual.
One of the best resources on ARC I found, is Chris Parker's WWDC talk on ARC Internals. If you haven't seen it yet, you should definitely check it out — the general part on ARC starts around the 8 minute mark, while the details start about 29 minutes in.
Your example code is correct. ARC makes those calls for you.
It ARC doesn't, however, "completely takes over" a newbie would still need to understand memory management. But like apple says it lets you concentrate on object ownership instead of retain counts.
For example if you don't modify your NSObject <Protocol> *_delegate; with __weak or __unsafe_unretained you will still create a retain cycle.
Yes, you're right. ARC pretty much takes the hassle of doing memory management out of your hands and has the compiler deal with all that stuff. Sit back, relax, and worry more about writing the code you want rather than causing trivial memory management issues :)

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.

Strange variable allocation in iOS book

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.