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 Development

Reply
 
LinkBack Thread Tools Display Modes
Old 01-07-2010, 07:27 PM   #1 (permalink)
MMS
Registered Member
 
Join Date: Nov 2009
Location: Connecticut
Posts: 95
MMS is on a distinguished road
Default 2 Questions re: Memory management in table view app-

Hello!

I am hoping that someone can help me out with two questions regarding memory management in a tableview based application.

In the viewDidLoad method, I populated the table with a list of items:

- (void)viewDidLoad {
[super viewDidLoad];
tableList = [[NSMutableArray alloc] init];
[tableList addObject:@"Object1"];
[tableList addObject:@"Object2"];
[tableList addObject:@"Object3"];
[self setTitle:@"Home"];

I then released the tableList in viewDidUnload. But, when I run the app with Leaks it has an issue with the first line of code: tableList = [[NSMutableArray alloc] init];. I am at a loss.


Next, I formatted the cells like so:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

[[cell textLabel] setText:[[tableList objectAtIndex:indexPath.row] retain]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosur eIndicator];

return cell;


Is autorelease the correct way to release here? Do I need to release the label separately?
MMS is offline   Reply With Quote
Old 01-07-2010, 08:26 PM   #2 (permalink)
Emphasizing Fundamentals
 
BrianSlick's Avatar
 
Join Date: Jul 2009
Location: NoVA / DC Area
Age: 36
Posts: 7,990
BrianSlick has a spectacular aura about
Default

Quote:
Originally Posted by MMS View Post
Hello!

I am hoping that someone can help me out with two questions regarding memory management in a tableview based application.

In the viewDidLoad method, I populated the table with a list of items:

- (void)viewDidLoad {
[super viewDidLoad];
tableList = [[NSMutableArray alloc] init];
[tableList addObject:@"Object1"];
[tableList addObject:@"Object2"];
[tableList addObject:@"Object3"];
[self setTitle:@"Home"];

I then released the tableList in viewDidUnload. But, when I run the app with Leaks it has an issue with the first line of code: tableList = [[NSMutableArray alloc] init];. I am at a loss.
Don't use instance variables directly. See the properties link in my signature for more info.

Quote:
Originally Posted by MMS View Post
Next, I formatted the cells like so:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

[[cell textLabel] setText:[[tableList objectAtIndex:indexPath.row] retain]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosur eIndicator];

return cell;


Is autorelease the correct way to release here? Do I need to release the label separately?
The autorelease is fine. The retain is a problem.
__________________
BriTer Ideas LLC - Professional iOS App Development. Available for hire.

SlickShopper 2 | Free NSLog utility | Leave a PayPal donation.

Are you a newbie? Things you should read:
Definitive Guide To Properties | UITableView Series | Guide To Troubleshooting | Model Object Overview

Do you sit at a desk all day? Walk instead! Follow along with my treadmill desk adventures.
BrianSlick is offline   Reply With Quote
Old 01-08-2010, 07:10 AM   #3 (permalink)
MMS
Registered Member
 
Join Date: Nov 2009
Location: Connecticut
Posts: 95
MMS is on a distinguished road
Default

Quote:
Originally Posted by BrianSlick View Post
Don't use instance variables directly. See the properties link in my signature for more info.



The autorelease is fine. The retain is a problem.
Brian,

Thank you for writing. I did read your tutorial before I wrote this question. (Also the documentation from Apple. There is a lot of new vocabulary for me...but I am trying to get what I'm doing.) I understand that the first part of my question pertains directly to figures 8 and 9 of your tutorial, and that I'm making a mistake in using the instance variable directly. Where you lose me is where rather than Myclass *myInstanceVariable =... It's Myclass *newItem=... I am confused about what my newItem would be.
But, I know that if I do this: NSMutableArray *tableList = [[NSMutableArray alloc] init]; I get a ton of warnings that I am hiding myInstanceVariable.

Last edited by MMS; 01-08-2010 at 08:51 AM.
MMS is offline   Reply With Quote
Old 01-08-2010, 09:04 AM   #4 (permalink)
Emphasizing Fundamentals
 
BrianSlick's Avatar
 
Join Date: Jul 2009
Location: NoVA / DC Area
Age: 36
Posts: 7,990
BrianSlick has a spectacular aura about
Default

You didn't retain the cell, you retained the string you were putting in to the text label.

As far as the cell itself, you should release anything created with alloc, new, copy, or retain. The dequeueReusableCell line does not involve any of those, so that line of code does not produce an object that you should release.

So the complication arises if there is no cell available for reuse. The return from that call in that case is nil. The whole "if (cell == nil)" part is for the case of "there was no cell available to reuse, therefore you must build a new one".

Let's simplify the code a bit to see what's going on:

Code:
1.  cell = [... dequeue...];
2.  if (cell == nil)
3.  {
4.     cell = [[.... alloc] init];
5.  }
6.  return cell;
Case A - There is a cell available
Line 1: gets populate with an object you don't need to release
Line 2: is false
Line 3-5: never happen
Line 6: return an object you didn't need to release, so no problem.

Case B - No cell is available.
Line 1: is nil
Line 2: is true
Line 4: creates an object that you DO need to release
Line 6: return an object you were supposed to release, but didn't. That's a leak.

The issue here is that there are 2 possible creation points - 1 where a manual release is required, one where it isn't - but only one return point. So you have 2 possible solutions: 1) The return needs to somehow know the difference, or 2) make a change so that both creation points have the same behavior. If #1 is possible, I don't know how to do it, so let's focus on #2.

Case C - Make a return release necessary
This would be done by changing the dequeue line: add a retain.
Code:
UITableViewCell *cell = [[tableView dequeueReusableCellWithIdentifier:CellIdentifier] retain];
This object now must be manually released in either case, and this would be done by changing the return line:
Code:
return [cell autorelease];
However, even though in this case the only way a new cell will be created is if the cell variable is nil, in general it is a bad idea to have an variable that could change later contain an object that needs to be released. That's just begging for a leak. This is probably why pretty much every example does:

Case D - Make a return release unnecessary
This would be done by changing the cell creation line #4:
Code:
cell = [[[... alloc] init] autorelease];
Now regardless of new-vs.-reused, no further release of the cell is necessary.
__________________
BriTer Ideas LLC - Professional iOS App Development. Available for hire.

SlickShopper 2 | Free NSLog utility | Leave a PayPal donation.

Are you a newbie? Things you should read:
Definitive Guide To Properties | UITableView Series | Guide To Troubleshooting | Model Object Overview

Do you sit at a desk all day? Walk instead! Follow along with my treadmill desk adventures.
BrianSlick is offline   Reply With Quote
Old 01-08-2010, 09:11 AM   #5 (permalink)
Emphasizing Fundamentals
 
BrianSlick's Avatar
 
Join Date: Jul 2009
Location: NoVA / DC Area
Age: 36
Posts: 7,990
BrianSlick has a spectacular aura about
Default

Instance variable:
Code:
Myclass *myInstanceVariable;
Local variable:
Code:
Myclass *newItem=...
Quote:
But, I know that if I do this: NSMutableArray *tableList = [[NSMutableArray alloc] init]; I get a ton of warnings that I am hiding myInstanceVariable.
With the NSMutableArray * part at the beginning, you are declaring a new variable - a LOCAL variable. However, in this case, your local variable has the same name as your instance variable. Don't do that.
__________________
BriTer Ideas LLC - Professional iOS App Development. Available for hire.

SlickShopper 2 | Free NSLog utility | Leave a PayPal donation.

Are you a newbie? Things you should read:
Definitive Guide To Properties | UITableView Series | Guide To Troubleshooting | Model Object Overview

Do you sit at a desk all day? Walk instead! Follow along with my treadmill desk adventures.
BrianSlick is offline   Reply With Quote
Old 01-08-2010, 10:42 AM   #6 (permalink)
MMS
Registered Member
 
Join Date: Nov 2009
Location: Connecticut
Posts: 95
MMS is on a distinguished road
Default

Quote:
Originally Posted by BrianSlick View Post
Instance variable:
Code:
Myclass *myInstanceVariable;
Local variable:
Code:
Myclass *newItem=...


With the NSMutableArray * part at the beginning, you are declaring a new variable - a LOCAL variable. However, in this case, your local variable has the same name as your instance variable. Don't do that.
Now I've crashed entirely- App loads and then crashes.

Here's what I tried-

In header- created the instance variable- NSMutableArray *tableList;
@property (nonatomic,retain) NSMutableArray *tableList;

In implementation:

@synthesize tableList=tableList; (you did say it was OK for the property and the variable to have the same name)

In viewDidLoad:

NSMutableArray *HomeList= [[NSMutableArray Alloc] init]]
[self settableList: HomeList]; (***I received a warning that the viewcontroller might not respond to settableList***)
[HomeList addobject:@"Object1"];
[HomeList addobject:@"Object2"];
[self setTitle:@"Home"];


When I tried build and go- the app opened the loading screen and then crashed. When I undid every change that I had made, then tried build and go- the same thing- loading screen, then crash.

I am confused and I have more questions-

I have used the instance variable "tableList" in every header and implementation file in a drill-down app. Is that a problem?

If I do not use the instance variable directly in the implementation file, then do I need to replace every use of the instance variable?
MMS is offline   Reply With Quote
Old 01-08-2010, 11:27 AM   #7 (permalink)
Emphasizing Fundamentals
 
BrianSlick's Avatar
 
Join Date: Jul 2009
Location: NoVA / DC Area
Age: 36
Posts: 7,990
BrianSlick has a spectacular aura about
Default

Quote:
Originally Posted by MMS View Post
Now I've crashed entirely- App loads and then crashes.

Here's what I tried-

In header- created the instance variable- NSMutableArray *tableList;
@property (nonatomic,retain) NSMutableArray *tableList;

In implementation:

@synthesize tableList=tableList; (you did say it was OK for the property and the variable to have the same name)
That is fine, although if you do that, there isn't much of a reason to do name=name. Just do @synthesize name;

Quote:
Originally Posted by MMS View Post
In viewDidLoad:

NSMutableArray *HomeList= [[NSMutableArray Alloc] init]]
[self settableList: HomeList]; (***I received a warning that the viewcontroller might not respond to settableList***)
[HomeList addobject:@"Object1"];
[HomeList addobject:@"Object2"];
[self setTitle:@"Home"];
setTableList:

By convention, variables should begin with a lowercase letter, so homeList.

You didn't show it here, so I'll add that you need to release homeList here before you leave viewDidLoad.

Quote:
Originally Posted by MMS View Post
When I tried build and go- the app opened the loading screen and then crashed. When I undid every change that I had made, then tried build and go- the same thing- loading screen, then crash.
It crashed because settableList doesn't exist, so it failed on the attempt. Don't ignore warnings; fix them.

Quote:
Originally Posted by MMS View Post
I am confused and I have more questions-

I have used the instance variable "tableList" in every header and implementation file in a drill-down app. Is that a problem?
Not at all. Just keep in mind that each one is unique to each class, so you have to keep passing that array to each controller in order for each one to operate on the same data.

Quote:
Originally Posted by MMS View Post
If I do not use the instance variable directly in the implementation file, then do I need to replace every use of the instance variable?
I don't understand the question.
__________________
BriTer Ideas LLC - Professional iOS App Development. Available for hire.

SlickShopper 2 | Free NSLog utility | Leave a PayPal donation.

Are you a newbie? Things you should read:
Definitive Guide To Properties | UITableView Series | Guide To Troubleshooting | Model Object Overview

Do you sit at a desk all day? Walk instead! Follow along with my treadmill desk adventures.
BrianSlick is offline   Reply With Quote
Old 01-08-2010, 11:33 AM   #8 (permalink)
MMS
Registered Member
 
Join Date: Nov 2009
Location: Connecticut
Posts: 95
MMS is on a distinguished road
Default

Quote:
Originally Posted by BrianSlick View Post
That is fine, although if you do that, there isn't much of a reason to do name=name. Just do @synthesize name;



setTableList:

By convention, variables should begin with a lowercase letter, so homeList.

You didn't show it here, so I'll add that you need to release homeList here before you leave viewDidLoad.



It crashed because settableList doesn't exist, so it failed on the attempt. Don't ignore warnings; fix them.



Not at all. Just keep in mind that each one is unique to each class, so you have to keep passing that array to each controller in order for each one to operate on the same data.



I don't understand the question.

What I meant by the last question is that myInstanceVariable- tableList appears many times in my implementation file, not just in the viewDidLoad- e.g.

number of rows in table-

return [tableList count];

Or pushing view controllers-

if ([[tableList objectAtIndex:indexPath.row] isEqual:@"Ferrovia Railway Station"]) ...

Should I be replacing those uses of my instance variable with my local variable?
MMS is offline   Reply With Quote
Old 01-08-2010, 11:41 AM   #9 (permalink)
Emphasizing Fundamentals
 
BrianSlick's Avatar
 
Join Date: Jul 2009
Location: NoVA / DC Area
Age: 36
Posts: 7,990
BrianSlick has a spectacular aura about
Default

Oh, I see. Well, there's probably a difference between what you can do, and what I do.

Any time you are simply reading the value, you can use the instance variable directly. If you are attempting to switch objects, then you should not use the instance variable directly.

I never use instance variables directly, with the exceptions as noted in my properties thread. So those same examples in any of my programs would look like:

Code:
return [[self tableList] count];

if ([[[self tableList] objectAtIndex:....)
Whether or not you even have a local variable is up to you. If you wanted to, you could certainly do this:

Code:
NSMutableArray *theList = [self tableList];
If you do that, might as well use it, so then the code becomes:

Code:
return [theList count];

if ([[theList objectAtIndex....)
__________________
BriTer Ideas LLC - Professional iOS App Development. Available for hire.

SlickShopper 2 | Free NSLog utility | Leave a PayPal donation.

Are you a newbie? Things you should read:
Definitive Guide To Properties | UITableView Series | Guide To Troubleshooting | Model Object Overview

Do you sit at a desk all day? Walk instead! Follow along with my treadmill desk adventures.
BrianSlick is offline   Reply With Quote
Old 01-08-2010, 12:02 PM   #10 (permalink)
MMS
Registered Member
 
Join Date: Nov 2009
Location: Connecticut
Posts: 95
MMS is on a distinguished road
Default

Quote:
Originally Posted by BrianSlick View Post
Oh, I see. Well, there's probably a difference between what you can do, and what I do.

Any time you are simply reading the value, you can use the instance variable directly. If you are attempting to switch objects, then you should not use the instance variable directly.

I never use instance variables directly, with the exceptions as noted in my properties thread. So those same examples in any of my programs would look like:

Code:
return [[self tableList] count];

if ([[[self tableList] objectAtIndex:....)
Whether or not you even have a local variable is up to you. If you wanted to, you could certainly do this:

Code:
NSMutableArray *theList = [self tableList];
If you do that, might as well use it, so then the code becomes:

Code:
return [theList count];

if ([[theList objectAtIndex....)
In the above example is *theList supposed to be a local variable? The same one that was used in viewDidload?

And, if, in the viewDidLoad I use a local variable, and I add the objects to the local variable, then don't I need to use the local variable in if ([[someVariable objectAtIndex...)?

Also, I assume since I retained the property tableList in the the header file, that I need to release it in the implementation file? Where should I release it?

Can you recommend a good source for me to read more? I'd like to actually understand why I have an instance variable when everything that I'm getting and setting seams to depend on the local variable.

When I've added scrollViews they've had an instance variable and a property, and been released in the dealloc method. Leaks isn't telling me that I have memory problems there...??

Last edited by MMS; 01-08-2010 at 12:12 PM.
MMS is offline   Reply With Quote
Old 01-08-2010, 12:07 PM   #11 (permalink)
Emphasizing Fundamentals
 
BrianSlick's Avatar
 
Join Date: Jul 2009
Location: NoVA / DC Area
Age: 36
Posts: 7,990
BrianSlick has a spectacular aura about
Default

See the tips link in my signature for some book recommendations. Sounds like you need some C basics.

Code:
- (void)someMethod
{
   TheClass *theVariable = ....;   // This is a local variable


}   // After this point, the local variable no longer exists
The point of instance variables is to be able to access them in any method in your class.

The point of properties is to access your instance variables in a memory-management-friendly way.
__________________
BriTer Ideas LLC - Professional iOS App Development. Available for hire.

SlickShopper 2 | Free NSLog utility | Leave a PayPal donation.

Are you a newbie? Things you should read:
Definitive Guide To Properties | UITableView Series | Guide To Troubleshooting | Model Object Overview

Do you sit at a desk all day? Walk instead! Follow along with my treadmill desk adventures.
BrianSlick is offline   Reply With Quote
Old 01-08-2010, 12:38 PM   #12 (permalink)
MMS
Registered Member
 
Join Date: Nov 2009
Location: Connecticut
Posts: 95
MMS is on a distinguished road
Default

Quote:
Originally Posted by BrianSlick View Post
See the tips link in my signature for some book recommendations. Sounds like you need some C basics.

Code:
- (void)someMethod
{
   TheClass *theVariable = ....;   // This is a local variable


}   // After this point, the local variable no longer exists
The point of instance variables is to be able to access them in any method in your class.

The point of properties is to access your instance variables in a memory-management-friendly way.
Thank you. That actually made a world of sense of sense to me. I will check out your reading suggestions.
MMS is offline   Reply With Quote
Reply

Bookmarks

Tags
memory alloc help, memory leak, tableviewcell

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 Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 340
14 members and 326 guests
akacaj, alexP, ClerurcifeDer, Domele, Duncan C, givensur, GraffitiCircus, JmayLive, michelle, NetGuru, NSString, Paul Slocum, Sloshmonster, soohyun
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,650
Threads: 94,114
Posts: 402,883
Top Poster: BrianSlick (7,990)
Welcome to our newest member, soohyun
Powered by vBadvanced CMPS v3.1.0

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