在iOS上使用ARC的内存管理

时间:2012-02-18 03:27:27

标签: ios pointers automatic-ref-counting instances

根据我刚刚解决的问题(我将在帖子中发布我的问题的答案,可以在这里找到答案:My former question,快速提出问题(更多是好奇心事)

问题是我有这个包含自定义单元格对象的UITableView。每次进入此视图时,我都会为UITableView生成新单元格,如下所示:

    if (cell == nil)
{
    [[NSBundle mainBundle] loadNibNamed:@"UploadCellView" owner:self options:nil];

    cell = customCell;
}

在标准方法中会发生这种情况:

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

现在的问题是我的自定义单元格对象会侦听有关在后台发生的上传对象的NSNotifications,因此他们可以将其模型数据更新为其标签和进度条等。就像这样(这是来自自定义的方法)单元格对象):

-(void) uploadProgress: (NSNotification*)notification
{
NSDictionary *userInfo = [notification userInfo];

NSNumber *uploadID = [userInfo valueForKey:@"uploadID"];

if (uploadID.integerValue == uploadActivity.uploadID)
{
    UIProgressView *theProgressBar = (UIProgressView*)[self viewWithTag:progressBarTag];

    [theProgressBar setProgress:(uploadActivity.percentageDone / 100) animated:YES];

    UILabel *statusText = (UILabel*)[self viewWithTag:percentageTag];

    [statusText setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", uploadActivity.percentageDone, uploadActivity.totalMBUploaded, uploadActivity.totalMBToUpload]];
}
}

上传完成后,他们只需执行此操作:

-(void) uploadFinished: (NSNotification*)notification
{
NSDictionary *userInfo = [notification userInfo];

NSNumber *uploadID = [userInfo valueForKey:@"uploadID"];

if (uploadID.integerValue == uploadActivity.uploadID)
{        
    [self setUploadComplete];

    [[ApplicationActivities getSharedActivities] markUploadAsFinished:uploadActivity];

    NSLog(@"BEGINNING RELOAD");
    [parentTable reloadData];
    NSLog(@"ENDING RELOAD");
}
}

现在的问题是他们打电话给他们拥有的桌面视图。当tableview包含在其中的视图消失时,旧的自定义单元格对象仍然在后台获取NSNotfications。然后,当完成上传时,前表视图中的旧自定义单元格对象仍会尝试调用此时设置的parentTable属性,现在导致调用随机垃圾内存。

我解决这个问题的方法是保持在表格中创建所有单元格对象的数组,然后在视图被解除时让它们停止侦听:

-(void) viewWillDisappear:(BOOL)animated
{
    for (UploadCell *aCell in lol)
    {
        [aCell stopListening];
    }

    [self.navigationController popViewControllerAnimated:YES];
}

但这似乎有点像黑客。如何在视图被解除时确保删除自定义单元格对象?因为当视图再次初始化时,新的单元格无论如何都是简单的,所以我没有使用旧的单元格。

自定义视图单元格有一个强大的属性指针指向它们所关联的tableview,但我认为ARC会确保TableView指针不会失效吗?显然它是以某种方式。也许是因为在弹出时删除了包含的视图?

2 个答案:

答案 0 :(得分:1)

听起来这些单元格有一个指向UITableViewDataSource类的retain属性。

它们应该具有assign属性,然后在释放表视图时它们将被正确释放(如果您的单元格保留它,则它当前不能被释放)。

此外,通过覆盖单元格didMoveToSuperview方法,单元格应在从表格视图中删除时关闭通知:

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];
    if ( [self superview] == nil )
    {
        [self unsubscribeFromYourNotifications];
    }
}

如果他们滚出屏幕就不会浪费资源来更新事物。

答案 1 :(得分:0)

您是否考虑过单独的更新模型,该模型在uploadID和侦听通知的单元格之间保留地图?这样,单元格不负责更新表本身,更新模型会这样做。当表格消失后,您可以关闭更新模型。