何时应该释放我的数组?

8
我是一名有用的助手,可以为您进行文本翻译。
我正在从互联网上解析一些JSON数据,并将它们添加到一个数组中,该数组是我的UITableView的数据源。我不确定何时应该释放我的数组?
.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);

    items = [[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;
    }

2
“我应该什么时候发布我的X?” - 尽快发布吧! ;) - Mitch Wheat
你能发布更完整的代码吗?按照现在的写法,它无法工作(或编译)。 - kubi
更新了更完整的代码。 - Sheehan Alam
7个回答

9

首先,如果您想在items上调用addObject:方法,请将其声明为NSMutableArray实例。

其次,声明它为属性,这样如果您多次获取它,则旧值会在您执行时被释放。

self.items = [NSMutableArray array];

释放它的正确时机是在dealloc方法中。


2

如果您:

  • 在detail views中使用didSelectRowAtIndexPath:方法并将数据传递给它们
  • 在cellForRowAtIndexPath:方法中定义自定义UITableViewCell样式
  • 在其他地方使用这些数据

最好的做法是声明一个实例变量并在.m文件中synthesize它,在适当的操作中使用,并在dealloc方法中释放。

您可以在刷新表格上显示的数据的位置使用一个可能的释放点。

示例:

我从我的应用程序中的API中获取数组中的字典,然后使用类似以下的内容。

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

2
释放内存时,有时会在错误的位置导致内存泄漏。在分配内存之前,可以使用类似于if() {...release}的条件语句来避免这种情况。尚未经过测试,但此类释放可以避免内存泄漏。请注意保留HTML标签。

0

很明显你的数组item将被UITableView用来展示数据。

首先在你的.h类中将其声明为实例变量。

.h类

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

@end

在你的.m类中。
@synthesis iMyArray;

你填充数组的代码应该是

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];

现在在dealloc中释放你的数组实例。

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

@Sheehan Alam:你试过使用我的答案了吗? - Jhaliya - Praveen Sharma
1
dealloc方法中不需要if语句。 - Holger Frohloff

0

正确的方法是将其作为.h类中的属性,因为您已将其声明为属性:始终使用self分配属性。

您的语句items=[[NSMutableArray alloc] init];

是错误的。(使用self)还因为您的属性是retain类型,所以在其上使用alloc会增加保留计数。这会导致泄漏。

因此,在viewDidLoad中使用以下方式

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

然后在 dealloc 中释放你的 items 数组,并在 viewDidUnload 中将其设置为 nil。
- (void)viewDidUnload {
    [super viewDidUnload];
    self.items=nil;
}

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

希望现在你能明白如何使用它了。

1
我想补充一点,你不应该使用setter方法来释放内存,而是直接使用ivar。 - (void)dealloc { [items release]; [super dealloc]; } - Holger Frohloff
实际上,不使用retain setter,直接将ivar分配给alloc/init是完全可以的。在任何情况下,都有一个+1的保留计数,并且您还可以获得不必将另一个对象转储到正在增长的autorelease池中的额外好处。此外,Holger提出了一个很好的观点。这主要是传统和风格,但没有打破有效的东西的意义。 - FeifanZ

0

最常见的方法是将items变量作为类的属性,因为你可能需要在tableView:cellForRowAtIndexPath:方法中使用它。

因此,将其作为属性变量,你可以在dealloc方法中释放它。


0
根据苹果公司关于UITableView reloadData方法的文档:
“[...] 为了提高效率,表视图只会重新显示那些可见的行”
这意味着只要表格正在使用中,您就不应该释放items数组,也就是说,您必须将该数组声明为属性。
首先,因为如果您滚动视图,仍需要items信息来显示下面或上面的行。
其次,通过成为属性,您可以确保如果您赋予items新值,先前的值将被释放。
最后,释放属性的常见位置是在dealloc方法中,具体取决于您在viewDidUnload方法中的实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接