Objective c 使用UITableView的UIViewController中可能存在内存泄漏

Objective c 使用UITableView的UIViewController中可能存在内存泄漏,objective-c,xcode,cocoa-touch,uitableview,uiviewcontroller,Objective C,Xcode,Cocoa Touch,Uitableview,Uiviewcontroller,我有一个UIViewController,它是以模式呈现的。当我观看内存分配工具时,当视图出现时,内存使用会增加,但当视图退出时,内存不会释放。 如果我一直打开和关闭视图,内存就会越来越高。 仪器没有报告内存泄漏! 这可能是什么原因造成的?视图控制器代码如下(我跳过了didSelectRow代码)。 Dealloc总是被称为 编辑-我正在使用圆弧 h 编辑------------- 有些事情似乎不对劲。我已经在单元格alloc中添加了一个NSLog,它从未被调用,即使单元格已经创建 PowerU

我有一个UIViewController,它是以模式呈现的。当我观看内存分配工具时,当视图出现时,内存使用会增加,但当视图退出时,内存不会释放。 如果我一直打开和关闭视图,内存就会越来越高。 仪器没有报告内存泄漏! 这可能是什么原因造成的?视图控制器代码如下(我跳过了didSelectRow代码)。 Dealloc总是被称为

编辑-我正在使用圆弧

h

编辑------------- 有些事情似乎不对劲。我已经在单元格alloc中添加了一个NSLog,它从未被调用,即使单元格已经创建

PowerUpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        NSLog(@"new cell");
        cell = [[PowerUpCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
编辑7月1日------ 我添加了一个导航控制器,现在使用push而不是modal,这个问题仍然存在。 我已经用仪器在视图之间来回移动了几次,拍摄了大量的照片,这些单元格似乎仍然挂在周围,因为这个屏幕截图显示了手势识别器仍然在以前的视图中。
[编辑]

在VIEWWILLEXPENCE方法中,您是否打印出来以查看通过else子句的频率。在我看来,您似乎将您的workOutSingleUseToDisplay和workOutFullUseToDisplay方法称为。每次调用它们时,您都在分配_singleUseArray和_fullUseArray。仅仅因为您移入和移出视图,并不意味着它调用dealloc,或者它将自动释放您当前的阵列。我认为您看到的是,当您移出视图时,它不会释放这两个阵列,而是尝试重新分配它们

[原件]
在viewDidLoad中,执行alloc。在您的dealloc中,我没有看到[footer release]。这可能是你的漏洞!!!我也没有看到发布您的_singleUseArray或_fullUseArray

我不确定是否得到答案,但您的代码中有一些奇怪的地方:

您正在使用弱属性:

@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet OutlineTextUILabel *starCountLbl;
但根据(搜索“弱”),
属性与
分配
非常相似

在你身上,你有

self.tableView = nil;
self.starCountLbl = nil;
我很确定生成的这些属性的setter根本不会释放它们

但是如果您像这样声明属性:

@property (nonatomic, retain) IBOutlet UITableView *tableView;
@property (nonatomic, retain) IBOutlet OutlineTextUILabel *starCountLbl;
生成的setter如下所示

(void)setTableView(UITableView *)newTableView {
    [tableView release];
    if(newTableView != nil)
        tableView = [newTableView retain];
}

您的属性将被释放。

至少,使用泄漏仪器来监控内存泄漏。分配工具实际上不会显示内存泄漏。如果运行Analyze,您将看到可能导致泄漏的线路。

这是您的代码:

 PowerUpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 if (cell == nil) {
    NSLog(@"new cell");
    cell = [[PowerUpCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
 }
你看,
cell
不会是
nil
。。。这在API文档中针对
dequeueReusableCellWithIdentifier:
进行了说明:

返回值

具有关联标识符的UITableViewCell对象,如果可重用单元队列中不存在此类对象,则为nil

无论如何,如果有泄漏,可能是由以下原因造成的:

_singleUseArray = [[NSMutableArray alloc] init];
_singleUseArray = [[NSMutableArray alloc] init];

当你宣布

NSMutableArray *_singleUseArray;
NSMutableArray *_fullUseArray;
我想,默认情况下,这两个都被分配了一个
\u strong
限定符。我不太确定,但这可能是问题的真正原因。换个说法怎么样

NSMutableArray * __weak _singleUseArray;
NSMutableArray * __weak _fullUseArray;
另外,在宣布

首先将其分配到
nil
以删除以前的引用,怎么样

_singleUseArray = nil;
_singleUseArray = [[NSMutableArray alloc] init];


这是因为您将IBOutlets用作
,而不是使用

我实际上认为这是XCode环境中的一个缺陷,因为它应该警告您这种行为


作为一种最佳实践,我建议让XCode通过将视图拖动到Interface Builder中的代码来生成IBOutlets,以避免此类恼人的陷阱。

看起来您已经找到了一些解决方法,但以防万一这会有所帮助:

1) 确保在调试时没有打开僵尸,因为这会导致对象在您认为应该解除锁定后挂起(编辑方案->运行->诊断)

2) 您使用的是ARC,所以我假设您的故事板/笔尖中有故事板或至少原型UITableView单元?如果是这样,那么下面的NSLog()从未被调用的原因是因为dequeueReusableCellWithIdentifier调用知道通过定义的cellIdentifier从这些原型单元创建单元。很方便

PowerUpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        NSLog(@"new cell");
        cell = [[PowerUpCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }

您必须依靠UITableView来管理UITableViewCells的缓存,并适当地释放它们。因此,他们可能只是在闲逛,因为您的UITableView没有发布(尽管我想您是这么说的)。

我使用的是ARC,因此无法手动发布。我尝试添加_singleUseArray=nil_fullUseArray=nil;页脚=零;你应该在你的第一篇文章中告诉我关于ARC的事情,因为我认为它决定了答案。很抱歉。我将把它添加到问题中。我已经将2个数组alloc移动到viewDidLoad,因此它们肯定只会被调用一次,但内存模式仍然相同。每次关闭时都会调用视图控制器dealloc。还有其他想法吗?我实际上只是在dealloc中添加了self.tableView=nil和self.starCountLbl=nil,同时试图找到没有发布的内容。实际上不需要它,因为它们是弱引用,并且在释放视图控制器时释放。在视图内部,您将使用PerformMonMainThread。这是不需要的,ViewWillDisplay发生在主线程上。我使用此方法只是为了设置waitUntilDone:是,因此我现在在绘制表之前已填充数组。请尝试以下操作:[self-workOutFullUseToDisplay]。您确实意识到Objective-C是顺序的,对吗?我本来就有,但在调用下一个方法之前,不确定它是否能完成workOutSingleUseToDisplay方法。如果不需要,我会移除它。ThxI已修复:-)如果我将tableView的IBOutlet更改为strong而不是Slong,则free的m
_singleUseArray = [[NSMutableArray alloc] init];
_fullUseArray = [[NSMutableArray alloc] init];
_singleUseArray = nil;
_singleUseArray = [[NSMutableArray alloc] init];
_fulUseArray = nil;
_fullUseArray = [[NSMutableArray alloc] init];
PowerUpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        NSLog(@"new cell");
        cell = [[PowerUpCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }