0

我已经升级了 Xcode,并收到了大量的分析器警告,如下所示:

在第 25 行分配并存储到“oneCopy”中的对象的潜在泄漏

谁能指出我正确的方向?

@implementation NSDictionary(DeepMutableCopy)
-(NSMutableDictionary *)mutableDeepCopy
{
    NSMutableDictionary *ret = [[NSMutableDictionary alloc] initWithCapacity:[self count]];
    NSArray *keys = [self allKeys];
    for (id key in keys)
    {
        id oneValue = [self valueForKey:key];
        id oneCopy = nil;

        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])
            oneCopy = [oneValue mutableDeepCopy];
        else if ([oneValue respondsToSelector:@selector(mutableCopy)])
            oneCopy = [oneValue mutableCopy];
        if (oneCopy == nil)
            oneCopy = [oneValue copy];
        [ret setValue:oneCopy forKey:key];
    }
    return ret;
}
@end

显示行号的屏幕截图:
在此处输入图像描述

#import "NSDictionary-DeepMutableCopy.h"


@implementation NSDictionary(DeepMutableCopy)
-(NSMutableDictionary *)mutableDeepCopy
{
    //NSMutableDictionary *ret = [[NSMutableDictionary alloc] initWithCapacity:[self count]];
    NSMutableDictionary *ret = [NSMutableDictionary dictionaryWithCapacity:[self count]];
    NSArray *keys = [self allKeys];
    for (id key in keys)
    {
        id oneValue = [self valueForKey:key];
        id oneCopy = nil;

        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])
            oneCopy = [oneValue mutableDeepCopy];
        else if ([oneValue respondsToSelector:@selector(mutableCopy)])
            oneCopy = [oneValue mutableCopy];
        if (oneCopy == nil)
            oneCopy = [oneValue copy];
        [ret setValue:oneCopy forKey:key];
        [oneCopy release];
    }
    return ret;

}
@end
4

2 回答 2

1

首先解决您的第二个问题,而不是[[NSMutableDictionary alloc] initWithCapacity:[self count]]您可以使用[NSMutableDictionary dictionaryWithCapacity:[self count]]which 将返回一个自动释放的对象,您必须自己在调用代码中保留它。

另一方面,如果您希望它返回一个保留的对象而不抛出错误,您可以重命名您的方法以以单词 copy 开头 -我认为这正是您在这种情况下想要做的。我的其余回复假设您已经走这条路。

我最初的回答如下:您不会在每次迭代结束时发布 oneCopy。尝试[oneCopy release];[ret setValue:oneCopy forKey:key];.

然而,正如Alexsander Akers 指出的那样,编译器认为 -mutableDeepCopy 的引用计数为 0。因此,如果您按照上面的建议重命名并[oneCopy release]按照我最初的建议包含它应该处理这两个问题。如果没有,请务必查看他引用的问题中的其他一些解决方案。

例子:

@implementation NSDictionary(DeepMutableCopy)
-(NSMutableDictionary *)copyWithDeepCopiedValues
{
    NSMutableDictionary *ret = [[NSMutableDictionary alloc] initWithCapacity:[self count]];

    NSArray *keys = [self allKeys];
    for (id key in keys)
    {
        id oneValue = [self valueForKey:key];
        id oneCopy = nil;

        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])
            oneCopy = [oneValue copyWithDeepCopiedValues];
        else if ([oneValue respondsToSelector:@selector(mutableCopy)])
            oneCopy = [oneValue mutableCopy];
        if (oneCopy == nil)
            oneCopy = [oneValue copy];
        [ret setObject:oneCopy forKey:key];

        [oneCopy release];
    }

    return ret;
}
@end
于 2011-11-09T22:08:17.063 回答
0

这里有两个问题。首先,正如@David Brainer-Banker 所说,您需要oneCopy在每次迭代结束时通过放置[oneCopy release]; after you set[ret setValue:oneCopy forKey:key];` 来释放。

不正确的引用计数递减是第二个问题。这是因为oneCopy对象可能有一个+1或一个0引用计数。-copy和返回的对象-mutableCopy有一个+1引用计数,但返回的对象-deepMutableCopy有一个0引用计数,因为它不在new, copy, or create(et al.) 系列中。

这个问题与这个问题完全相同,并且有一些很好的回答。

于 2011-11-10T19:56:57.793 回答