IPhone - copyWithZone泄漏

时间:2010-10-12 16:32:07

标签: iphone memory-leaks constructor copy copywithzone

在设备上测试我的应用程序,当我调用自定义对象的副本时,它会返回泄漏,我无法理解为什么。

这是电话:

NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:5];
for (SinglePart *sp in [copyFrom partList]) {
    [arr addObject:[sp copy]];
}
self.partList = arr;
[arr release];

这是方法:

- (id)copyWithZone:(NSZone *)zone {
    SinglePart *copy = [[[self class] allocWithZone:zone] initWithSinglePart:self];
    [copy loadImage];
    return copy;
}

这是copyWithZone调用的方法:

- (id)initWithSinglePart:(SinglePart *)copyFrom {
    if (self = [super init]) {
        self.imagePath = [copyFrom.imagePath copy];
        self.color = [UIColor colorWithCGColor:copyFrom.color.CGColor];
        self.hasOwnColor = copyFrom.hasOwnColor;
        self.blendingMode = copyFrom.blendingMode;
    }
    return self;
 }

3 个答案:

答案 0 :(得分:4)

copy返回一个具有保留计数1的新对象。这意味着你需要释放你没有做的新对象。

NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:5];
for (SinglePart *sp in [copyFrom partList]) {
    SingPart *theCopy = [sp copy];
    [arr addObject:theCopy];
    [theCopy release];
}
self.partList = arr;
[arr release];

甚至您的自定义copyWithZone:方法都会在对象中进行,但不会自动释放它,这是copy方法的预期行为。复制必须像retain或init一样平衡,这意味着你必须在某些时候平衡它与释放。

最后,您的initWithSinglePart:方法也会泄漏imagePath。在这种情况下,如果您将imagePath属性声明为copy而不是retain,那么您根本不需要手动执行此操作。然后你只需分配值,让属性设置器为你做。

// Header
@property (copy) NSString *imagePath;

// Now this will do the copy for you
self.imagePath = copyFrom.imagePath;

答案 1 :(得分:1)

此外,属性imagePath是使用retain还是copy语义定义的?

如果需要,您需要在此处添加自动释放:

self.imagePath = [[copyFrom.imagePath copy] autorelease];

因为默认的setter也会保留/复制它。

所以,你要么需要自动释放,要么省略“自我”。绕过默认的setter。

答案 2 :(得分:0)

您正在制作sp的副本,然后将其添加到阵列中。然后数组保留对象,因此您的保留计数现在为2。

最后释放arr,从而使其保留计数为1。

您应该向sp个对象添加其他版本,或者不使用copy

试试这个:

self.partList = [NSMutableArray arrayWithCapacity:5];
for (SinglePart *sp in [copyFrom partList]) {
    [arr addObject:sp];
}