Self syntax in iPhone development - iphone

What is the difference between the following two approaches for the self syntax to access the object properties:-
Approach 1:-
self.effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
self.effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
Approach 2:-
effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
effortView is defined as a property, and synthesized, to the Class addressed as self in Approach 1. Both of the approaches work.
I am using Xcode 4.0 iPhone SDK 4.3 on Mac 10.6.6.
Please enlighten me.
Thank you All

In the first syntax:
self.effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
self.effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
you are accessing both ivars through their accessor methods (usually, effortView to get, setEffortView to set).
In the second syntax:
effortView = [[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
effortView.effortTableView = [[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped];
you are accessing the effortView ivar directly (pointer assignment), while you are accessing effortTableView through its property accessor.
The difference is that using an accessor you obtain additional behavior. Like, with the standard set accessors generated by the #synthesize keyword for a retain property:
#property (nonatomic, retain) NSObject* property;
you get automatic retain count management (i.e., retain count will be automatically incremented on the assigned object; if the ivar had already a value, the object pointed to will have its retain count decreased). What this implies is that in your first example, you are causing 2 memory leaks. Indeed, (if the properties are declared as retain property) assigning to them will increase their retain count; but [[alloc] init] already gives back an object with a retain count of 1, so you don't need to increment it once more. Correct would be:
self.effortView = [[[EffortView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
self.effortView.effortTableView = [[[UITableView alloc]initWithFrame:CGRectMake(25, 25, 300, 420) style:UITableViewStyleGrouped] autorelease];
Overall, properties make much easier to deal with retain count management and are the suggested way to go with it, but you have to be aware of their "retain count" semantics and account for that.
I would suggest this article as an interesting reading.

If the property is declared like this
#property (nonatomic, assign) EffortView *effortView;
both approaches are equivalent. In the case the property is declared like this
#property (nonatomic, retain) EffortView *effortView;
the code [[EffortView alloc] init...]; first generates a retained EffortView instance and then the 'assignment' self.effortView = ... retains this instance again. Therefore to balance the retain count you have to release the generated instance.

The former uses the accessors methods generated by the synthesize statement.
The latter accesses the variable directly.

self.effortView uses the accessor methods generated by #synthesize to get and set the property, while effortView accesses the instance variable directly. Inside the class where the property is defined, the difference is most important when considering the setter: it automatically takes care of memory management. So if you've done this:
#property (nonatomic, retain) EffortView *effortView;
then the two approaches have different results. Approach 1 leaks in this case, as the setter retains the object and you +alloc it without a balanced -release.

Related

objective c class method returned value, assigned to weak/strong properties

I'm facing a bit of a confusion involving weak and strong properties. For the sake of brevity I won't include the entire code.
I created a class convenience method which returns a UIView object, and I implemented it in a UIView category as an alternative to subclassing.
#implementation UIView (CSMonthView)
+ (UIView *)monthViewFromDateArray:(NSArray *)arrayOfAllShiftsAndEvents withNibOwner:(id)owner selectedDate:(NSDate *)selectedDate withCompletionHandler:(void(^)(CSCalendarButton *selectedButton))block
{ // .. do some stuff
// Create an instance of UIView
UIView *monthView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320.0, 200.0)];
// Create UIButtons and set the passed down 'owner' value, as the target for an
// action event.
// Add UIButton as subviews to monthView....
return monthView;
}
I should note that inside the method I do not have anything pointing to monthView.
Now inside the implementation of the 'owner', which is a class called CSCalendarViewController, I create the above UIView by calling the class convenience method and assign it to a UIView property called _monthView.
#interface CSCalendarViewController : UIViewController
#property (weak, nonatomic) UIView *monthView;
#end
#implementation CSCalendarViewController
__weak CSCalendarViewController *capturedSelf = self;
// Create the current month buttons and populate with values.
_monthView = [UIView monthViewFromDateArray:_arrayOfAllShiftsAndEvents withNibOwner:self selectedDate:_selectedDate withCompletionHandler:^(CSCalendarButton *selectedButton) {
capturedSelf.selectedButton = selectedButton;
[capturedSelf.selectedButton setSelected:YES];
}
Now my confusion is this. Even though I defined the property 'monthView' as weak, 'monthView' still holds on to the value of the returned UIView.
If I go ahead and do something like this:
_monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];
The compiler gives a warning (as it should) saying "Assigned retained object to weak variable".
Why am I not getting the same error message when I assign 'monthView' to the UIView that returns from the class method?
I don't have a deep understanding when it comes to pre-ARC memory management, and I think I'm missing something obvious. Thanks.
'monthView' still holds on to the value of the returned UIView.
It won't for long. This question demonstrates the underlying workings of ARC, and how it is a translation to the traditional retain/release methods, rather than a whole new memory management system.
Pre ARC
Before ARC, there was no concept of weak or strong, instead it referred to retain and assign. Assigning to variables did nothing to the reference count, it was up to the developer to manage it.
Now, in regards to the memory management policies, a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”, will return a retained object (Documentation). This meant, on assignment to a variable, the developer didn't need to explicitly retain (they had to explicitly release, or autorelease):
// Will have a retain count of 1 here
var = [NSString alloc] initWithString:#"Test"];
// Will have a retain count of 2 here
var = [[NSString alloc] initWithString:#"Test"] retain]
// Will have a retain count of 1 here, but will be released later on automatically
var = [[NSString alloc] initWithString:#"Test"] autorelease];
// Will have a retain count of 0 here, and will be released before it reaches the variable!
var = [[NSString alloc] initWithString:#"Test"] release];
Methods that don't have that naming convention, suggest they return an autoreleased object. The developer needs to say something explicitly, to keep the object around longer:
// Will have a retain count of 1 here, but will be released later on automatically
var = [NSString stringWithString:#"Test"];
// Will have a retain count of 1 here
var = [[NSString alloc] initWithString:#"Test"] retain]
// Will have a retain count of 1 here, but will be released twice later on (Over-released!)
var = [[NSString alloc] initWithString:#"Test"] autorelease];
// Will have a retain count of 0 here, and will be released again later on (Over-released!)
var = [[NSString stringWithString:#"Test"] release];
ARC + MRC
ARC removes this unnecessary need of releasing and retaining, and instead decides what to do with the memory management based on the type of variable it will be assigned to. This doesn't mean the memory management model changed; it is still all retain and release under the hood. As such, how does this affect you? For brevity, this answer will only take into account weak variables.
Assigning to a weak variable does not do anything with the retain count of the object. Lets see a practical example to explain:
__weak UIView* monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];
Because (in reality, behind the ARCness) this is returning a retained object, but weak variables don't affect the retain count, the compiler has found the earliest point to release the object in order to prevent a memory leak; on allocation! As such, it will be translated to the following, and cause an error:
UIView* monthView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)] release];
Now, in regards to monthViewFromDateArray:, this is suggesting to the compiler (due to its name), that it will return an autoreleased object (Documentation). Because the compiler is aware that an autoreleased object will be released automatically later on in the run loop (when the autorelease pool is drained), it will not insert a release call like before. As such, the assignment to a weak variable isn't an issue, but it's only really valid within the scope it's being used in.
Say we have method
+(UIView*) create {
return [[UIView alloc] init];
}
It is converted to this when compiled
+(UIView*) create {
return [[[UIView alloc] init] autorelease];
}
Now here:
UIView* __weak view;
//warning here
view = [[UIView alloc] init]; //1
view = [AppDelegate create]; //2
The first line is converted to this:
tempVar = [[UIView alloc] init];
storeWeak(tempVar, &view); //view = tempVar and marked as weak
[view release]; //view is nil after this because retain count == 0 (assignment to nil is done in release internally)
The second line:
tempVar = [MyClass create];
[tempVar retainAutoreleasedReturnValue];
storeWeak(tempVar, &view); //view = tempVar and marked as weak
[release tempVar]; //view is not nil because tempVar is autoreleased later
If we have the code like this:
#autoreleasepool {
view = [[UIView alloc] init];
//view is nil here
view = [AppDelegate create];
//view equals to the return value
}
//view becomes nil here because [AppDelegate create] return value is released
You can see all of this by looking at code disassembly.

viewDidLoad runs before instance variables are given values

What I have is a advertisement Class that has an instance variable that will receive the banner url:
#interface Advertisement : UIViewController {
}
#property (nonatomic, retain) NSString *image;
Now, in my app delegate I am initializing the ad class and giving the instance variable "image" a value.
//setup the ad
Advertisement *theAdView = [[Advertisement alloc] init];
theAdView.view.frame = CGRectMake(0.0, self.window.frame.size.height-120.0, 320.0, 76.0);
theAdView.view.clipsToBounds = YES;
theAdView.view.tag = AD_TAG;
NSLog(#"Added the image");
theAdView.image = theAd.banner;
theAdView.nid = theAd.nid;
[self.window addSubview:theAdView.view];
[self.window bringSubviewToFront:theAdView.view];
In the advertisement class' viewDidLoad method I want the value of the "image." However I get a null value. So it looks like the class is initializing before it gets a chance to get the instance variables.
I think I found a solution before, but I can't remember exactly what. I believe it had something to do with setting another variable that does not use (nonatomic, retain)... I'm not sure.
a UIViewController will load it's view (from nib or call the loadview method if you've overriden it) when you attempt to access it's 'view' property. In your case, 1 easy result would be to move the lines
theAdView.image = theAd.banner;
theAdView.nid = theAd.nid;
to before anything that accesses the view property, like
theAdView.view.frame = CGRectMake(0.0, self.window.frame.size.height-120.0, 320.0, 76.0);
or a better one would be to accept the image and nid as properties in a new initializer

Object leak using "retain"

I have a property defined with retain attribute which I am synthesizing:
#property (nonatomic, retain) UISwitch *mySwitch;
And inside my loadView I am doing this:
self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
And finally inside my dealloc I am doing this:
self.mySwitch = nil;
Am I leaking this object (mySwitch) as I have used one alloc? Should I autorelease it while assigning it frame?
Please suggest.
The line:
self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
Actually calls retain twice- once for the alloc and again in the assignment to self.mySwitch (which is a property you've specified should retain any values assigned to it.) The fix I have been told is best is to add a call to autorelease on the line, making it:
self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];
Yes, you are leaking. You are creating an owned object with +alloc/-initWithFrame:, then assigning that owned object to a property marked retain. This creates a second owned reference to the object. At this point, you leak your original owned reference, which causes the object itself to leak.
The correct behavior here is to call -autorelease on the object before assigning it to the property.
self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];
On a tangential note, it's not recommended that you access properties inside of -dealloc. The two reasons generally given for this are 1) this will broadcast KVO notifications, which you don't want inside of -dealloc, and 2) if anyone overrides the setter (in this class or a subclass) it may not behave properly. The recommended approach is to simply release the underlying ivar, so you'd see something like the following instead:
[mySwitch release];
Assigning nil to the property is perfectly safe (and recommended) everywhere else.
As alternative to autorelease, if you need a tighter memory management this should work for you:
UISwitch *myswitch_tmp= [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
self.mySwitch = myswitch_tmp;
[myswitch_tmp release];
and later e.g. in dealloc
[mySwitch release];
Yes. You are leaking object. Remember one simple rule here:
if you used +alloc there is always must be corresponding -release.

iPhone memory management

I am newbie to iPhone programming. I am not using Interface Builder in my programming. I have some doubt about memory management, #property topics in iPhone.
Consider the following code
#interface LoadFlag : UIViewController {
UIImage *flag;
UIImageView *preview;
}
#property (nonatomic, retain) UIImageView *preview;
#property (nonatomic, retain) UIImage *flag;
...
#implementation LoadFlag
#synthesize preview;
#synthesize flag;
- (void)viewDidLoad
{
flag = [UIImage imageNamed:#"myImage.png"]];
NSLog(#"Preview: %d\n",[preview retainCount]); //Count: 0 but shouldn't it be 1 as I am retaining it in #property in interface file
preview=[[UIImageView alloc]init];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 1
preview.frame=CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
preview.image = flag;
[self.view addSubview:preview];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 2
[preview release];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 1
}
...
When & Why(what is the need) do I have to set #property with retain (in above case for UIImage & UIImageView) ? I saw this statement in many sample programs but didn't understood the need of it.
When I declare #property (nonatomic, retain) UIImageView *preview; statement the retain Count is 0. Why doesn't it increase by 1 inspite of retaining it in #property.
Also when I declare [self.view addSubview:preview]; then retain Count increments by 1 again. In this case does the "Autorelease pool" releases for us later or we have to take care of releasing it. I am not sure but I think that the Autorelease should handle it as we didn't explicitly retained it so why should we worry of releasing it.
Now, after the [preview release]; statement my count is 1. Now I don't need UIImageView anymore in my program so when and where should I release it so that the count becomes 0 and the memory gets deallocated. Again, I am not sure but I think that the Autorelease should handle it as we didn't explicitly retained it so why should we worry of releasing it. What will happen if I release it in -(void) dealloc method
In the statement -> flag = [UIImage imageNamed:#"myImage.png"]]; I haven't allocated any memory to flag but how can I still use it in my program. In this case if I do not allocate memory then who allocates & deallocates memory to it or is the "flag" just a reference pointing to -> [UIImage imageNamed:#"myImage.png"]];. If it is a reference only then do i need to release it.
You say...
I am newbie to iPhone programming. I
am not using Interface Builder in my
programming.
Wait. What? Why not? Not using IB as someone new to the environment is generally an indication that you are doing your app the hard way. Not using IB for app development is reserved for rare, generally fairly advanced, situations.
Question 1
This means that the synthesized property accessor messages will include an automatic retain when the message is called (but ONLY when the message is called, see next).
Question 2
This is because you are not using the property accessor message, you are just assigning to the member variable. If you use:
self.preview = [[[UIImageView alloc] init] autorelease];
The resulting retain count will be one (+1 for the init, -1 for the autorelease, +1 for the retain on the message).
N.B.
You will get the same retain count (one) if you do this:
preview = [[UIImageView alloc] init];
(+1 for the init, not using the property accessor message so no extra retain). Up to you which way you go with.
Question 3
The addSubview will increment the retain count again because the preview will be stored in a collection which will retain it's objects.
So yes, Basically if you are handing an object off to another object to manage (as is the case with addSubview) you can set it to autorelease and it will be released by the other object. However, since you are storing the UIImageVIew in a retained property, you will need to release it yourself (see next).
Question 4
Because you are keeping the preview object as retained property, you will need to release it in your dealloc message. So in my Question 2 example, you allocate the object, autorelease it, but assign it to retained property, so the retain count after all that will be one, you are adding it to a collection which will also retain it. When the view is cleaned up the collection will decrement the retain count, but you will need to call release as well, because you stored it in a retained property. So in your dealloc:
[preview release];
Question 5
imageNamed is a helper message that does the allocation, initialization and autorelease. So basically it is equivalent to saying.
NSData * dataForImage = get data from the myImage.png here ...
self.flag = [[[UIImage alloc] initWithData:dataForImage] autorelease];
You are storing it in a retained property (because I use self.flag in the above example), so you will need to release it in the dealloc message.
When you write
flag = [UIImage imageNamed:#"myImage.png"]];
you are assigning to the instance variable directly, bypassing the property accessor. Instead you need to use the dot-notation:
self.flag = [UIImage imageNamed:#"myImage.png"]];
That explains your retain count problem.
I found it useful to declare the instance variables with a different name, like _flag for a property flag. Associate the two by writing
#property .... flag = _flag;
That way you will not accidentally use the variable directly. You can, of course, still do so if the need arises.
You use retain to claim ownership of an object. This essentially means that when something is assigned to the property, you ensure that it's there for as long as the owning object needs it.
#property ... is a statement of your the interface of your class. It doesn't mean there is a value for the property in question, only that "Instances of LoadClass have a flag property which is retained by it". Not until you actually assign values to the properties of an instance will things be retained.
This is because UIView claims ownership of its subviews.
Your object might not need it, but UIView still needs it.
It's autoreleased by UIImage.
You should read the full guide on Memory Management by Apple. I try to think of memory management as owning objects or not... it helps.
Question 2: The #property statement in your #interface is really just a directive to the compiler to automatically generate accessor methods for an instance variable that have the characteristics you specify. #property doesn't cause any actions to happen when you run your code. The compiler will look at the #property line and generate invisible accessor code for you.
#property (nonatomic, retain) UIImageView *preview;
would cause the compiler to generate accessor methods that look something like this:
- (void) setPreview:(UIImageView *)newValue {
[self willChangeValueForKey:#"preview"];
if (preview != newValue) {
[preview release];
preview = [newValue retain];
}
[self didChangeValueForKey:#"preview"];
}
- (UIImageView *) preview {
return preview;
}
#property is a timesaver for you; it directs the compiler to generate accessor code for your variables that are efficient but invisible. If you didn't use #property, you'd have to write accessor methods similar to the above in your custom class.

(iphone) basic memory management question

I have used following 2 patterns to create a view.
#property (retain, nonatomic) SomeView* someView;
...
// First pattern
self.someView = [[SomeView alloc] initWithFrame frame];
// Second pattern
SomeView* aSomeView = [[SomeView alloc] initWithFrame];
self.someView = aSomeView;
[aSomeView release];
Now, looking back at this code, the first pattern's method should be changed to
self.someView = [[[SomeView alloc] initWithFrame frame] autorelease];
shouldn't it?
I feel dumb :(
Look at it like this:
[[SomeView alloc] initWithFrame: frame];
The above line creates an object and gives it a retain count of 1.
self.someView = [[SomeView alloc] initWithFrame: frame];
This line leaves it with a retain count of two, because the someView property is declared with retain:
#property (**retain**, nonatomic) SomeView* someView;
So, doing it this way leaves your someView property pointing to an object with retain count of 2. You can do it this way if you add an autorelease call to it:
self.someView = [[[SomeView alloc] initWithFrame: frame] autorelease];
Your second pattern is better, if you ask me. You create an object with a retain count of one. You assign it to a retaining property (now it has a retain count of 2) and then you release the original variable, leaving the object again with a retain count of 1. It's three lines where you might want only one, but it makes sense in the right context. Additionally, it's usually best to avoid using autorelease outside of an alloc or copy method since its usually an indication you don't fully understand memory management in Obj-C.
And as a commenter said in the comments to the question, don't feel dumb. None of this is intuitive at first. Nobody picks up a guitar and plays like Hendrix their first time.
Yes, you are right. autorelease means "release a bit later".
Yes, I think you should change that. With self.someView = you are calling the setter which increases the retain count.
Now, looking back at this code, 1's method should be changed to self.someView = [[[SomeView alloc] initWithFrame frame] autorelease];
shouldn't it?
correct
a)
SomeView * view = [[SomeView alloc] initWithFrame:frame];
self.someView = view;
[view release], view = nil;
b)
self.someView = [[[SomeView alloc] initWithFrame:frame] autorelease];
many people prefer b, simply because it is less to type.
i prefer an approach similar to a because:
defects (such as over-releasing) are often exposed near the call site, rather than when the pool is destroyed (this often means you have to load up Instruments in Zombie mode to locate the callsite)
it performs better and minimizes memory usage (in general, but not much in this specific case)
you have more opportunity to check for invalid states and results
you have a chance to init/configure the view/object for its usage before adding it to self, which is usually preferred