我是Cocoa和Objective-C的新手。目前我正在开发一个相当基本的应用程序来测试我的知识,并将我正在阅读的一些内容付诸实践。一切正常,但Leaks报告了一些问题。
这些泄漏似乎都没有直接适用于我编写的代码(我已阅读并尝试遵循Apple关于内存分配的规则)。目前我的项目使用垃圾收集,我正在开发Snow Leopard。运行AnalysisTool发现我的代码没有问题(除了一些命名约定警告)。
目前我的应用程序使用了我连接到NSArrayController的NSTableView。与NSTableView交互似乎会导致泄漏报告问题(排序表列和其他标准用户交互等操作)。这让我相信我对NSArrayController(以及我对其内容源的实现)的使用是罪魁祸首。
目前,NSArrayController从我的应用程序委托中处理的NSMutableArray(计时器)接收其内容,如下所示:
- (id) init
{
if (self = [super init])
{
timers = [NSMutableArray array];
}
return self;
}
- (void) dealloc
{
[timers release];
[super dealloc];
}
在Interface Builder中,我的NSArrayController将其对象控制器设置为Timing类,定义如下:
@interface Timing : NSObject {
NSString *desc;
NSDate *timestamp;
bool active;
}
@end
@implementation Timing
-(id) init
{
if (self = [super init])
{
desc = @"New timing";
timestamp = [[NSDate alloc] init];
active = false;
}
return self;
}
-(void) dealloc
{
[timestamp release];
[super dealloc];
}
@end
我使用标准的Cocoa绑定来连接Add和Remove按钮来操作TableView,这些似乎工作正常(例如,单击Add会在TableView中创建一个值为'New timing'的行)。
Leaks报告称负责的图书馆是AppKit和CoreGraphics。虽然,老实说,我还是Leaks工具的新手 - 所以我可能会错误地读取它的输出。如果有帮助,我会放置其输出here的屏幕截图。如果有人能指出我正确的方向,那将非常感激。
顺便说一句,我也在尝试手动将对象添加到timers数组而不使用Cocoa绑定。这就是我想出的:
Timing *timingInstance = [[Timing alloc] init];
[timers addObject:timingInstance];
[timingInstance release];
[timersController setContent:timers];
[timersTableView reloadData];
同样,这似乎有效,但我认为最好问专家!
答案 0 :(得分:2)
timers
数组的内存管理不是完全正确。使用array
工厂方法将返回已经自动释放的NSMutableArray
实例,因此该对象的生命周期(可能)仅限于当前运行循环的结束,并且它将结束 - 在dealloc方法中调用release
时发布。正确的方法如下:
- (id) init
{
if (self = [super init])
{
timers = [[NSMutableArray alloc] initWithCapacity:0];
}
return self;
}
此方法将为您提供一个NSMutableArray
实例,其保留计数为1,当您在dealloc方法中调用release
时,该实例将降至零(并正确释放内存)。通过alloc
方法中init
的调用,可以平衡release
方法中对dealloc
的调用。我注意到这是您在NSDate
课程中用于Timing
对象的确切模式,因此您已经熟悉了这个想法。
答案 1 :(得分:2)
您写的代码没有泄露。在leaks
下运行时,Cocoa框架有时会生成错误的泄漏报告,因为在框架实现中使用的单例和缓存等有时会显示为泄漏,即使它们不是。
最好运行ObjectAlloc和/或ObjectGraph工具,以了解对象何时被分配和释放。
答案 2 :(得分:1)
目前我的项目正在使用 垃圾收集和我正在发展 在雪豹上
我不明白。你正在使用垃圾收集吗?如果是这样,那么GC负责为你释放物品,所以你在任何地方使用“释放”都绝对没有。启用GC后,将忽略释放调用。您只在自己管理内存时才使用发行版,即GC关闭时。此外,你的dealloc方法也没有做任何事情。在GC中,从未使用过该方法。当你创建一个对象,然后你完成它,你告诉GC,通过将它设置为零来摆脱对象是可以的。这就是你要做的一切。不需要“释放”或需要dealloc方法。根据需要将事情设置为零或不。