我有一个循环参考.如何在Objective-C中创建弱引用?

Toz*_*zar 20 iphone weak-references objective-c circular-reference

我正在开发一个iPhone应用程序.我有一个类的对象Row需要释放该类的许多对象Block.每个Block当前都有一个保留类的实例变量的属性Row.

@interface Block : UIImageView {
  Row *yCoord;
}
@property (nonatomic,retain) Row *yCoord;
@end
Run Code Online (Sandbox Code Playgroud)

每个Row包含NSMutableArray这些块中的一个.

@interface Row : NSObject {
    NSMutableArray *blocks;
}
-(void)addBlock:(Block*)aBlock;
@end

@implementation Row
-(void)addBlock:(Block*)aBlock {
    [blocks addObject:aBlock];
    aBlock.yCoord = self;
}
@end
Run Code Online (Sandbox Code Playgroud)

我知道这是一个循环参考.Apple的文档声明,为了使用循环引用释放对象,我需要一个弱引用而不是一个强引用(一个保留属性),但它没有贯彻并解释我究竟是如何做到的.我计划同时释放和释放一行中的所有块以及行本身.如何在每个块中将弱引用设置为"父"行?

Qui*_*lor 19

编辑:由于提问者澄清他没有使用垃圾收集(iPhone目前不支持它),我的建议是通过只让一个对象保留另一个来避免周期,就像你对委托一样.使用属性时,使用"assign"而不是"retain"来实现此目的.例如:

@property (nonatomic,assign) Row *yCoord;
Run Code Online (Sandbox Code Playgroud)

我的答案的其余部分与Objective-C 2.0和GC相关的"弱引用"有关.


当您使用垃圾收集(10.5+)时,通过为变量声明添加前缀来创建弱引用__weak.当您分配给该变量时,GC(如果已启用)会跟踪该引用,并且如果对引用对象的所有强引用都消失,则会自动将其归零.(如果未启用GC,__weak则忽略该属性.)

因此,你可以安全地修改上面的答案,以便更好地利用垃圾收集(目前在10.5以上,也许有一天在iPhone上),如下所示:(参见相关的Apple文档.)

@property (nonatomic,assign) __weak Row *yCoord;
Run Code Online (Sandbox Code Playgroud)

引用Chris Hanson(您可以在哪里找到更多详细信息):

"通过为实例变量声明添加前缀__weak,您可以告诉垃圾收集器,如果它是对象的唯一引用,则该对象应被视为可收集."

我通过说"如果没有对象的非弱引用"来澄清这一点.一旦删除了最后一个强引用,就可以收集该对象,并且所有弱引用将自动归零.

注意:这与创建弱引用没有直接关系,但也有一个__strong属性,但由于Objective-C对象变量默认是强引用,因此它通常仅用于原始C指针,如结构或基元,垃圾收集器不会被视为根,如果您没有将它们声明为强,则会从您下面收集垃圾收集器.(缺乏__weak可能导致保留周期和内存泄漏,缺乏__strong可能导致内存踩踏,并且非确定性地发生真正奇怪和阴险的错误,并且可能很难追踪.)


Cor*_*oyd 8

只需将其更改为assign而不是retain,不再使用循环引用.

@interface Block : UIImageView {
  Row *yCoord;
}
@property (nonatomic,assign) Row *yCoord;
@end
Run Code Online (Sandbox Code Playgroud)