合成的复制属性不会被ARC取消分配

时间:2012-03-05 15:55:15

标签: objective-c ios

在我的项目中,我正在管理几个 Drawing 对象。我正在尝试将 SmartPath 对象的副本添加到绘图对象。这有效。但是当图形被取消分配时, SmartPath 不会。我在 Drawing 的dealloc中添加了一些额外的代码,以显式设置清除指向 SmartPath 的指针。出于某种原因,这有效(保留计数为1)。我知道我可以复制SmartPath并将其分配给一个强参数来修复此泄漏。但我对IOS比较陌生,想知道如何正确地将复制参数与ARC结合使用。

以下是代码:

Drawing.h:

@interface Drawing : NSObject{
@private
    SmartPath* rawLinePath;         //path that is build up from straight lines between input points
    SmartPath* smoothLinePath;      //smoothened version of rawLinePath
}


@property(atomic,copy)SmartPath* rawLinePath;
@property(atomic,copy)SmartPath* smoothLinePath;

Drawing.m

@implementation Drawing
@synthesize rawLinePath;
@synthesize smoothLinePath;



-(id)init
{
    if (self = [super init])
    {        
        [NSThread detachNewThreadSelector:@selector(pointMonitor) 
                                 toTarget:self 
                               withObject:nil];  
    }
    return self;
}

-(void)dealloc{
    rawLinePath=nil;
}

SmartPath.m

/*
 * Init - set all variables in the correct state
 */
-(id)init
{
    if (self = [super init])
    {        
        visible=TRUE;
        color = [UIColor redColor].CGColor;
        width = SMARTPATH_LINE_WIDTH;
        path = CGPathCreateMutable();
        lock = [[NSLock alloc]init];
    }
    return self;
}

/*
 * dealloc - clean up after self 
 */
-(void)dealloc{
    CGPathRelease(path);
}

/*
 * copy method to be able to pass a SmartPath to a copy property
 */
-(id)copyWithZone:(NSZone *)zone{
    SmartPath *pathCopy = [[SmartPath allocWithZone: zone] init];
    pathCopy.visible =visible;
    pathCopy.color = color;
    pathCopy.width = width;
    return pathCopy;
}

我希望你们中任何人都知道这个问题的答案。 最好的问候

2 个答案:

答案 0 :(得分:2)

您的问题是致电-detachNewThreadSelector:toTarget:withObject:。这会保留targetself,并且在pointMonitor退出之前不会释放它。我怀疑这种情况永远不会发生,所以你已经有效地创建了一个保留循环。

你几乎不应该使用-detachNewThreadSelector:toTarget:withObject:。它可以创建无限数量的线程。相反,您通常应该使用调度队列,NSTimerNSOperation或其他异步机制。 NSThread个对象通常只适用于长期生产者/消费者线程(并且通常使用较新的工具(如调度队列)处理这些对象)。

我不确定pointMonitor做了什么,但是有什么理由它需要自己的线程吗?你可以做很多非常好的Cocoa开发,永远不会分叉线程。你能在这里使用NSTimer吗?请注意,大多数这些技术会一直保持目标直到它们发射(就像NSThread)。如果他们没有,你会在他们解雇时崩溃。

在不知道你想要做什么的情况下,我不确定推荐哪种方法。您可能希望将它们放在一起作为一个新问题。

答案 1 :(得分:0)

如果不使用下划线启动实例变量名,最终会得到代码,您永远不知道是使用访问器方法还是实例变量。因此,您永远无法确定是否制作了副本。

如果您在其他地方执行此操作,则很可能会对某个SmartPath对象的引用卡在某处。你在做什么创建NSLock对象?你需要做任何@synchronized不能用更少代码做的事吗?

如果您使用较新的Xcode版本,请删除所有实例变量和@synthesize语句。只需声明属性即可。

请原谅,但从init方法中删除线程只是生病了。