开发者

When should I release my array?

I am parsing some JSON from the internet and then adding them to an array which is the datasource for my UITableView. I am not sure when I should be releasing my array?

.h: items

@property(nonatomic,retain)NSMutableArray*  items;

.m: connectionDidFinishLoading

// fetch succeeded    
    NSString* json_string = [[NSString alloc] initWithData:retrievedData encoding:NSUTF8StringEncoding];

    //Check ST status
    int status =  [[[[json_string objectFromJSONString] valueForKey:@"response"] valueForKey:@"status"]intValue];
    //NSLog(@"Status: %d", status);

    item开发者_开发技巧s = [[NSMutableArray alloc] init];
    NSDictionary* messages = [[NSDictionary alloc] init]; 

    switch (status) {
        case 200:
            messages = [[[json_string objectFromJSONString] valueForKey:@"messages"] valueForKey:@"message"];

            for (NSDictionary *message in messages)
            {
                [items addObject:message];
            }
            [self.tableView reloadData];
        break;

        default:
        break;
    }


One, you might want to declare items as an instance of NSMutableArray if you intend to call addObject: on it.

Two, declare it as a property so that if you end up getting it multiple times the older value will be released when you do.

self.items = [NSMutableArray array];

And the correct point of releasing it would be dealloc.


Probably you don't want to release it immediately if you:

  • use didSelectRowAtIndexPath: method for detail views and pass this data to them
  • define custom UITableViewCell styles in cellForRowAtIndexPath: method
  • use this data elsewhere

Best practice is declare an instance variable and synthesize it in .m, use in appropriate operations and release in dealloc method.

One possible release point that you could use is where you refresh your data that shown on table.

Example:

I get dictionaries in an array from an API in my app and use something like that.

MyTableViewController.h

@interface MyTableViewController {
    NSMutableArray *items;
}

@property (nonatomic, retain) NSMutableArray *items;

@end

MyTableViewController.m

@implementation MyTableViewController

@synthesize items;

- (void)dealloc
{
    [items release];
    [super dealloc];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [items count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *cellIdentifier = @"FilesCellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }

    cell.textLabel.text = [[items objectAtIndex:indexPath.row] valueForKey:@"name"];
    cell.imageView.image = [UIImage imageNamed:[[NSString alloc] initWithFormat:@"filetype_%@.png", [[items objectAtIndex:indexPath.row] valueForKey:@"type"]]];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
        MyDetailViewController *detailViewController = [[MyDetailViewController alloc] initWithNibName:@"MyDetailViewController" bundle:[NSBundle mainBundle]];
        detailViewController.item = [items objectAtIndex:indexPath.row];
        [self.navigationController pushViewController:detailViewController animated:YES];
        [detailViewController release];
        detailViewController = nil;
    }
}

- (void)getItems
{
    [items release];
    items = [[NSMutableArray alloc] init];

    //Do some requests here

    for (NSDictionary *dict in results)
    {
        [items insertObject:dict atIndex:0];
    }

    [self.tableView reloadData];
    [self stopLoading];
}

@end


Releasing at wrong places some time lead to memory leaks, before allocation itself u can have a condition like if() { [...release]}.Not tested but this kind of release avoid leaks.


The most common is to have the items variable as an attribute of your class, once you will probably need it to use in your tableView:cellForRowAtIndexPath: method.

So, having it as an attribute variable you can release it on the dealloc method.


It's clear that your array item will be used by UITableView to show data.

First declare it as instance variable in your .h class.

.h class

@interface MyClass 
{
  MSMutableArray* items;
}
@property(nonatomic,retain) MSMutableArray* items;

@end

In your .m class.

@synthesis iMyArray;

And you code for filling the array should be

NSMutabelArray* itemsTemp = [[NSMutabelArray alloc] initWithCapacity:1];

messages = [[[json_string objectFromJSONString] valueForKey:@"messages"] valueForKey:@"message"];
[json_string release];

for (NSDictionary *message in messages) {
    NSLog(@"%@",[message valueForKey:@"body"]);
    [itemsTemp addObject:message];
}


self.items= itemsTemp;

[itemsTemp release];
itemsTemp = nil;

[self.tableView reloadData];

Now in dealloc release your array instance.

-(void) dealloc
{
   if(items )
   {
    [items release];
    items = nil ;
   }
   [super dealloc];
}


Proper way is make it property in .h class, since you have declared it as property: remember one thing always alloc a property by using self.

your statement items=[[NSMutableArray alloc] init];

is wrong.(use self) also since your property is retain type the using alloc on it increase retain count.that gives you a leak.

so use in this way in viewDidLoad

NSMutableArray *tempArray=[[NSMutableArray alloc] init];
self.items=tempArray;
[tempArray release];

then release your items array in dealloc and set it nil in viewDidUnload

- (void)viewDidUnload {
    [super viewDidUnload];
    self.items=nil;
}

- (void)dealloc {
    [self.items release];
[super dealloc];
}

Hope now you can understand how you should use this.


According to Apple's documentation of UITableView reloadData method:

"[...] For efficiency, the table view redisplays only those rows that are visible"

That means yo should not release the items array as long as the table is being used, i.e. you have to declare the array as a property.

First because if you scroll the view, you will still need the items information to display the rows below or above.

And second, because by being a property you ensure that a previous value is going to be released if you happen to assign a new value to items.

Finally, the common place to release a property is in the dealloc method and depending on your implementation in viewDidUnload method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜