Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Tutorials

Reply
 
LinkBack Thread Tools Display Modes
Old 10-18-2010, 08:03 AM   #26 (permalink)
Registered Member
 
Join Date: Mar 2010
Posts: 17
FatFatto is on a distinguished road
Default One of the best articles in the universe.

As many people have said, this is basically one of the best articles ever written, on any topic - ever - anywhere!

Rames - you know you're good - you are good!!! I can only add my thanks.

One suggestion, "Note that we are still responsible for doing the "release" in the "dealloc" method..."

Perhaps you should enlarge on this slightly so that people have the definitive explanation in one place; i.e. one would not (cannot) release unless it is of such and such type, etc. So, I suggest a small new subsection "releasing properly in dealloc".

Again I and everyone else can only say Thank You.
FatFatto is offline   Reply With Quote
Old 11-08-2010, 04:14 AM   #27 (permalink)
Registered Member
 
Join Date: Jul 2010
Posts: 3
khaleel8039 is on a distinguished road
Thumbs up thanks dude

its a great tutorial for beginners....... keep it up .waiting for more from you bye
khaleel8039 is offline   Reply With Quote
Old 01-07-2011, 02:34 PM   #28 (permalink)
Registered Member
 
Join Date: Dec 2010
Posts: 29
themkn is on a distinguished road
Default

Thank you very much for the tutorial. But there is something I don't understand. What is the difference between doing
Code:
 
    [textValue retain];
    [text release];
    text = textValue;
and

Code:
 
    [text release];
    [textValue retain];
    text = textValue;
The first one should be the correct one. But I don't see (logically) the difference. If you do first retain on textValue and then you release the variable text, can't it be that when you do text=textValue that the variable text is already deallocated (like the second one)?
themkn is offline   Reply With Quote
Old 01-09-2011, 02:39 PM   #29 (permalink)
Mobile Geek
 
Join Date: Aug 2008
Location: Florida, USA
Posts: 365
rames44 is on a distinguished road
Send a message via AIM to rames44 Send a message via Yahoo to rames44
Default

Quote:
Originally Posted by themkn View Post
Thank you very much for the tutorial. But there is something I don't understand. What is the difference between doing
Code:
 
    [textValue retain];
    [text release];
    text = textValue;
and

Code:
 
    [text release];
    [textValue retain];
    text = textValue;
The first one should be the correct one. But I don't see (logically) the difference. If you do first retain on textValue and then you release the variable text, can't it be that when you do text=textValue that the variable text is already deallocated (like the second one)?
Remember that the special situation we're discussing is when "text" and "textValue" point to the same object.

Suppose that we were the only one holding onto the object that "text" and "textValue" addresses. Thus, the reference count on that object is 1. In the first case, the "retain" increments the reference count to 2, the "release" decrements it to 1. The reference count never reaches zero, so the system doesn't deallocate the object.

In the latter case, the "release" decrements the reference count to 0, and then the retain tries to increment it to 1. Sounds the same, however, as soon as the reference count hits zero, the system deallocates the object. Deallocations aren't somehow "deferred until later" - they happen as soon as zero is hit. So, perhaps much later, you then try to access the value addressed by "text," and you get an exception. It's a hard-to-find bug.

If "text" and "textValue" point to different objects, then of course the "release" could cause the object addressed by "text" to be deallocated - that's entirely good and proper, and exactly what we want - in that case, the order doesn't really matter. It's only in this special "both point to the same object" case that the second order presents a problem - basically, it's a subtle bug. It isn't horribly likely to be triggered, since takes (effectively) something like:
Code:
   self.xyz = self.xyz;
to trigger it, but it can happen if you do something like
Code:
   self.xyz = [self doSomeOperationAndReturnAResult];
and there's some path where "doSomeOperationAndReturnAResult" could conceivably return "xyz".
__________________
For a little fun, check out my Biorhythms app
rames44 is offline   Reply With Quote
Old 01-09-2011, 02:44 PM   #30 (permalink)
Registered Member
 
Join Date: Dec 2010
Posts: 29
themkn is on a distinguished road
Default

Ah I missed the point that both variables are pointing to the same object . Thanks for your nice tutorial
themkn is offline   Reply With Quote
Old 03-01-2011, 04:25 AM   #31 (permalink)
Registered Member
 
Join Date: Oct 2010
Posts: 9
ofirbt is on a distinguished road
Default

The best post I've ever seen.
ofirbt is offline   Reply With Quote
Old 05-09-2011, 11:44 PM   #32 (permalink)
Registered Member
 
Join Date: May 2011
Posts: 1
dougjack is on a distinguished road
Thumbs up Thanks!!

Thank you for the incredibly clear and well-written post. After hours of searching on the web, this was a very welcome discovery.
dougjack is offline   Reply With Quote
Old 05-23-2011, 07:43 AM   #33 (permalink)
Registered Member
 
Join Date: May 2011
Posts: 1
Couicoui is on a distinguished road
Default Rule number 1 tweak

Hi there,
First of all i want to join the round of applause for this clear and hour saving post. I still have one question about memory management that this post raise :

Quote:
But you also can't do

Code:
- (MyObject *)getObject
{
    return [[MyObject alloc] init];
}
because you've broken rule # 1 - you allocated it, but you didn't release it. What you really need to be able to do is tell Objective C "I'm responsible for this object, so I want to release it, but I want the release to be delayed until whoever asked for this object has had a chance to use it."
I understand the issue, but suppose the calling function of getObject will be in charge of releasing the object, would that be an issue?

For example :
Code:
// The getter function
- (MyObject *)getObject
{
    return [[MyObject alloc] init];
}

// The caller function
- (void)doSomething
{
     MyObject *obj = [self getObject];
     
     // Do something with obj

     [obj release];

}
In that case we wouldnt have to use auto release, and we would know exactly when we release it. It might be a twisted way of programming, but id like to know if its a "clean" way of dealing with the issue, on a theoretical point of view.

Thanks a lot!
Couicoui is offline   Reply With Quote
Old 06-19-2011, 12:49 AM   #34 (permalink)
Registered Member
 
Join Date: Jun 2011
Posts: 1
manosf is on a distinguished road
Thumbs up One of the best articles I've read

Now, this was accurate, helpful, concise and thorough. Thank you very much for sharing this. It helped me clarify things and from what I've read, lots of other people too.
I wish you the best in all your endeavors.
manosf is offline   Reply With Quote
Old 06-24-2011, 04:04 PM   #35 (permalink)
Mobile Geek
 
Join Date: Aug 2008
Location: Florida, USA
Posts: 365
rames44 is on a distinguished road
Send a message via AIM to rames44 Send a message via Yahoo to rames44
Default

Quote:
Originally Posted by Couicoui View Post
Hi there,
First of all i want to join the round of applause for this clear and hour saving post. I still have one question about memory management that this post raise :



I understand the issue, but suppose the calling function of getObject will be in charge of releasing the object, would that be an issue?

For example :
Code:
// The getter function
- (MyObject *)getObject
{
    return [[MyObject alloc] init];
}

// The caller function
- (void)doSomething
{
     MyObject *obj = [self getObject];
     
     // Do something with obj

     [obj release];

}
In that case we wouldnt have to use auto release, and we would know exactly when we release it. It might be a twisted way of programming, but id like to know if its a "clean" way of dealing with the issue, on a theoretical point of view.

Thanks a lot!
Typically, you try not to create these kinds of special situations, because it's hard to remember the responsibilities. Joe Programmer who comes along after you is unlikely to realize that he has to release the object, because he's been so indoctrinated into The Three Rules.

If a callee creates an object, the autorelease pattern works just fine, of course - have the callee autorelease, and the object sticks around for the caller to use it and gets released later. The only "down side" to it is that the object may stick around longer than you like. If you were doing this inside a loop, for example, all the objects build up in the autorelease pool until you finally return from the message processing.

Situations where you should (or have to) use autoreleased objects and where you want to force those objects to get released on command are an application for your own autorelease pool.

Code:
- (void)doSomething
{
    for (int i = 0; i < 100000; i++)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        MyObject *obj = [self getAutoreleasedObject];
     
        // Do something with obj

        [pool drain];  // obj will be released here
        [pool release];
    }
}
In this case, the autoreleased objects get put into the autorelease pool we created, since it's the most "deeply nested" one. (There's still another one wrapping your message processing, but you can't get to that one.) When the pool is drained, all the objects that have built up inside it get released. Thus, this would release MyObject, plus any other autoreleased objects that might have been created during the call to getAutoreleasedObject.

In this situation, without the autorelease pool, you'd build up 100,000 instances of MyObject in the surrounding autorelease pool until you returned and it got drained. Here, you clean up after yourself on each iteration of the loop.

(Needless to say, you probably shouldn't be doing this kind of thing in a UI thread, but there are worker thread situations that resemble this.)
__________________
For a little fun, check out my Biorhythms app
rames44 is offline   Reply With Quote
Old 07-05-2011, 05:02 AM   #36 (permalink)
Registered Member
 
Join Date: Jul 2011
Posts: 2
tofeeq is on a distinguished road
Default

Thanks for this important information which helped me much.

I have some points that I didn't understand:

the automatic setter method is:
Code:
-(void) setText:(NSString *)textValue
{
    [textValue retain];
    [text release];
    text = textValue;
}
let's take example
Code:
NSString *text;
@property (nonatomic, retain) NSString *text;
@syn...

----
   
view DId load:
    self.text = @"hi";
now the line in view did load will call the setter,
first line in setter [textValue retain]; will increase retain to 1
second [text release]; will decrease it to 0
now we got no retain count??
tofeeq is offline   Reply With Quote
Old 07-05-2011, 11:32 PM   #37 (permalink)
Mobile Geek
 
Join Date: Aug 2008
Location: Florida, USA
Posts: 365
rames44 is on a distinguished road
Send a message via AIM to rames44 Send a message via Yahoo to rames44
Default

Quote:
Originally Posted by tofeeq View Post
Thanks for this important information which helped me much.

I have some points that I didn't understand:

the automatic setter method is:
Code:
-(void) setText:(NSString *)textValue
{
    [textValue retain];
    [text release];
    text = textValue;
}
let's take example
Code:
NSString *text;
@property (nonatomic, retain) NSString *text;
@syn...

----
   
view DId load:
    self.text = @"hi";
now the line in view did load will call the setter,
first line in setter [textValue retain]; will increase retain to 1
second [text release]; will decrease it to 0
now we got no retain count??
If "textValue" and "text" refer to different objects, then [textValue retain] and [text release] obviously deal with different retain counts.

If "textValue" and "text" refer to the same object, then (since the object exists at the moment) its retain count must be non-zero before this code is executed. Thus, retaining it and then releasing it won't alter the retain count - it can't go to zero unless it was zero originally, and it can't be zero originally or it wouldn't exist.
__________________
For a little fun, check out my Biorhythms app
rames44 is offline   Reply With Quote
Old 07-06-2011, 01:16 AM   #38 (permalink)
Registered Member
 
Join Date: Jul 2011
Posts: 2
tofeeq is on a distinguished road
Default

Quote:
Originally Posted by rames44 View Post
If "textValue" and "text" refer to different objects, then [textValue retain] and [text release] obviously deal with different retain counts.

If "textValue" and "text" refer to the same object, then (since the object exists at the moment) its retain count must be non-zero before this code is executed. Thus, retaining it and then releasing it won't alter the retain count - it can't go to zero unless it was zero originally, and it can't be zero originally or it wouldn't exist.

Thanks for your replay.
So, is my code for declaring a string and giving it an initial value is correct?
tofeeq is offline   Reply With Quote
Old 07-09-2011, 09:18 AM   #39 (permalink)
Mobile Geek
 
Join Date: Aug 2008
Location: Florida, USA
Posts: 365
rames44 is on a distinguished road
Send a message via AIM to rames44 Send a message via Yahoo to rames44
Default

Quote:
Originally Posted by tofeeq View Post
Thanks for your replay.
So, is my code for declaring a string and giving it an initial value is correct?
If you're talking about
Code:
.h file:
NSString *text;
@property (nonatomic, retain) NSString *text;

.m file
@synthesize text;

----
   
viewDidLoad:
    self.text = @"hi";
then yes, this is quite correct. The "property" declaration indicates that your class will retain the string, and the "synthesize" will automatically create the appropriate code to do just that.
Code:
    self.text = @"hi";
will then call the synthesized "setter", causing the member variable to be set with a retained version of the string, releasing any prior contents.

You should also have a
Code:
  [text release];
in your class's "dealloc" method in order to ensure that whatever string is assigned to "text" is properly released when your class instance is deallocated. If you don't do that, you will have a potential memory leak.
__________________
For a little fun, check out my Biorhythms app
rames44 is offline   Reply With Quote
Old 08-04-2011, 02:00 AM   #40 (permalink)
Registered Member
 
Join Date: Aug 2011
Posts: 1
Caberry15 is on a distinguished road
Default

I am trying to do a similar quiz app and wanted to put images to questions. For instance if its a sports question I would put a sports picture, music question pic of guitar, etc.
Caberry15 is offline   Reply With Quote
Old 09-01-2011, 01:37 PM   #41 (permalink)
Registered Member
 
Join Date: Sep 2011
Posts: 1
applegal is on a distinguished road
Default

Thank you for the excellent tutorial ! It really helped clear up a few things for me.
applegal is offline   Reply With Quote
Old 09-01-2011, 06:55 PM   #42 (permalink)
Registered Member
 
Join Date: Sep 2011
Posts: 3
Excelcius is on a distinguished road
Default

Great post clear concise and thorough, Im currently busy swearing at several iPhone development books I wish you'd write a one !

I understood most of your posts but Im a little confused by the following

Quote:
Originally Posted by rames44 View Post
Code:
-(void)doSomething
{
    SomeObject *obj = [[SomeObject alloc] init];
    self.obj = obj;
    [obj release];
}
The first line creates an object. Since we "alloc'd and init'd" the object, it now has a retain count of one. Then we call the setter in the second line. The setter was presumably defined to retain the object, so that makes the retain count two. Then the third line releases the object once. This balances out the implicit retain in the first line, leaving the retain count at one, meaning that the only reference to the object is by the owner.
Why release obj surely the retained setter self.obj = obj, both releases and retains the pointer so the retain count remains at 1 not 2 and the final statement would reduce the retain count to 0 ?

Thanks
Excelcius is offline   Reply With Quote
Old 09-05-2011, 10:31 PM   #43 (permalink)
Mobile Geek
 
Join Date: Aug 2008
Location: Florida, USA
Posts: 365
rames44 is on a distinguished road
Send a message via AIM to rames44 Send a message via Yahoo to rames44
Default

Quote:
Originally Posted by Excelcius View Post
Great post clear concise and thorough, Im currently busy swearing at several iPhone development books I wish you'd write a one !

I understood most of your posts but Im a little confused by the following



Why release obj surely the retained setter self.obj = obj, both releases and retains the pointer so the retain count remains at 1 not 2 and the final statement would reduce the retain count to 0 ?

Thanks
self.obj = obj will release the OLD pointer (the previous "self.obj") and then will retain the one being set. The idea is that it disposes of the object that was previously being held, then retains the new one.
__________________
For a little fun, check out my Biorhythms app
rames44 is offline   Reply With Quote
Old 09-14-2011, 10:09 AM   #44 (permalink)
Registered Member
 
Join Date: Sep 2011
Posts: 3
Excelcius is on a distinguished road
Default

Quote:
Originally Posted by rames44 View Post
self.obj = obj will release the OLD pointer (the previous "self.obj") and then will retain the one being set. The idea is that it disposes of the object that was previously being held, then retains the new one.
Yes I understand that, as in this example from your tutorial

Code:
-(void) setText:(NSString *)textValue
{
    [textValue retain];
    [text release];
    text = textValue;
}
but what I mean is, surely if the obj setter is similar to the above code, then wouldn't the following code produce these results

Code:
-(void)doSomething
{
    SomeObject *obj = [[SomeObject alloc] init];   //retain count = 1
    self.obj = obj;                        //retain count = 1 (not 2)
    [obj release];                        //retain count = 0 (not 1)
}
just to clarify my rather confusing question heres your post

Quote:
As a result of this, it is almost always better to use the "self.text =" form instead of the "text =" form - the latter is quite likely to generate memory leaks. To use the "text=" form properly, one would have to do:
Code:
Code:
-(void)doSomething:(NSString *)input
{
    [input retain];
    [text release];
    text = input;
}
in order to make sure that the memory was handled properly. But guess what? This is essentially identical to the setter that was automatically generated for us, so why not just do it as:
Code:
Code:
-(void)doSomething:(NSString *)input
{
    self.text = input;
}
and save the aggravation and potential for bugs.

Carrying this a bit further, this is why you see code that looks like this so often:
Code:
Code:
-(void)doSomething
{
    SomeObject *obj = [[SomeObject alloc] init];
    self.obj = obj;
    [obj release];
}
The first line creates an object. Since we "alloc'd and init'd" the object, it now has a retain count of one. Then we call the setter in the second line. The setter was presumably defined to retain the object, so that makes the retain count two. Then the third line releases the object once. This balances out the implicit retain in the first line, leaving the retain count at one, meaning that the only reference to the object is by the owner.
Excelcius is offline   Reply With Quote
Old 09-16-2011, 06:28 PM   #45 (permalink)
Mobile Geek
 
Join Date: Aug 2008
Location: Florida, USA
Posts: 365
rames44 is on a distinguished road
Send a message via AIM to rames44 Send a message via Yahoo to rames44
Default

Quote:
Originally Posted by Excelcius View Post
Yes I understand that, as in this example from your tutorial

Code:
-(void) setText:(NSString *)textValue
{
    [textValue retain];
    [text release];
    text = textValue;
}
but what I mean is, surely if the obj setter is similar to the above code, then wouldn't the following code produce these results

Code:
-(void)doSomething
{
    SomeObject *obj = [[SomeObject alloc] init];   //retain count = 1
    self.obj = obj;                        //retain count = 1 (not 2)
    [obj release];                        //retain count = 0 (not 1)
}
Let's walk through it line by line, expanding into the subroutine.
Code:
SomeObject *obj = [[SomeObject alloc] init];
At this point, "obj" has been created and has a retain count of 1.

When "self.obj = obj" gets executed, this results in:
Code:
[textValue retain];
At this point, "textValue" (the parameter to the subroutine) refers to the same object as "obj", so "obj" now has a retain count of 2.
Code:
 [text release];
"text" does NOT refer to "obj" - it refers to whatever object was *previously* attached to the parent object. Thus, this decrements the retain count on the previous object, possibly releasing it, but does not alter obj's retain count.
Code:
text = textValue;
No alterations to the retain count.

Now we're back out of the subroutine
Code:
[obj release];
"obj" has its retain count decremented from 2 to 1.

Basically, "obj" starts with a retain count of 1 (from the alloc), and then has its retain count incremented when it is "attached" to "self". The retain count is then decremented with the explicit release. If I then did
Code:
self.obj = anotherObj
at that point, the "text" item inside the subroutine WOULD be referring to "obj" (since IT would now be the "old" object) and it would be released, decrementing its retain count to zero and causing the memory to be dealloc'd.
__________________
For a little fun, check out my Biorhythms app
rames44 is offline   Reply With Quote
Old 02-26-2012, 11:53 PM   #46 (permalink)
Registered Member
 
Join Date: Feb 2012
Posts: 1
Jumanji is on a distinguished road
Default

Quote:
Originally Posted by rames44 View Post
Let's walk through it line by line, expanding into the subroutine.
Code:
SomeObject *obj = [[SomeObject alloc] init];
At this point, "obj" has been created and has a retain count of 1.

When "self.obj = obj" gets executed, this results in:
Code:
[textValue retain];
At this point, "textValue" (the parameter to the subroutine) refers to the same object as "obj", so "obj" now has a retain count of 2.
Code:
 [text release];
"text" does NOT refer to "obj" - it refers to whatever object was *previously* attached to the parent object. Thus, this decrements the retain count on the previous object, possibly releasing it, but does not alter obj's retain count.
Code:
text = textValue;
No alterations to the retain count.

Now we're back out of the subroutine
Code:
[obj release];
"obj" has its retain count decremented from 2 to 1.

Basically, "obj" starts with a retain count of 1 (from the alloc), and then has its retain count incremented when it is "attached" to "self". The retain count is then decremented with the explicit release. If I then did
Code:
self.obj = anotherObj
at that point, the "text" item inside the subroutine WOULD be referring to "obj" (since IT would now be the "old" object) and it would be released, decrementing its retain count to zero and causing the memory to be dealloc'd.
just to say thanks nice tuts!!!
Jumanji is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 473
15 members and 458 guests
alexeir, David-T, Dj_kades, foslock, HemiMG, iAppDeveloper, jeroenkeij, LunarMoon, Mijator, Pauluz85, pipposanta, QuantumDoja, robsmy, sacha1996, usernametaken
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,679
Threads: 94,129
Posts: 402,928
Top Poster: BrianSlick (7,990)
Welcome to our newest member, xzoonxoom
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 09:23 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0