unsafe_unretained属性有什么用?

时间:2013-04-12 09:51:57

标签: iphone ios

我知道unsafe_unretained的定义。

所以我不指望任何人写出它的定义。

我想知道它在示例中的用法,以及它如何与内存管理一起使用。

3 个答案:

答案 0 :(得分:30)

unsafe_unretained仅存在于ARC(Automatic Reference Counting)中。它的工作方式类似于MRC中的assign(手动参考计数)。这些属性不会被保留。通常,您希望将这些属性用于委托,因为它们不需要保留它们的所有者。

weak属性类似unsafe_unretained,但它们的工作方式更为智能。释放分配给属性的对象时,弱引用自动变为nil,以避免在向该对象发送消息(其内存地址)时发生崩溃。

unsafe_unretained属性不会这样做。它们将始终保持分配给它的内存地址(除非您手动更改它),而不管与该地址关联的对象。在这种情况下,弱引用可以防止崩溃,但结果仍然不会如预期的那样。如果您的代码是有条理的并且写得很好,那么这不应该发生。

那么为什么要使用unsafe_unretained代替weak?弱引用仅适用于iOS 5及更高版本,因此如果您要构建面向iOS 4的ARC应用,则需要使用unsafe_unretained属性。再次,向已发布的属性发送消息并不是您想要在任何代码中拥有的任何内容。如果您的代码组织良好,那么您应该没有任何问题。

答案 1 :(得分:1)

在ARC之前,可以将委托或其他引用父项属性指定为assign以防止保留周期。随着ARC和更新的编译器的引入,您将使用unsafe_unretained

因此,只要您不需要引用的所有权,并且不需要或不想使用新的weak引用类型(在解除分配时将引用置空),您就可以使用它。

答案 2 :(得分:0)

以下是unsafe_unretained的具体用例。假设两个类相互引用,一个方向强,另一个方向弱。在第一类的dealloc期间,来自第二类的弱引用将已经为零,从而阻止进行适当的清理。用unsafe_unretained引用替换弱引用将解决此问题。请参阅下面的代码示例:

@class Foo;

@interface Bar: NSObject

//Replacing weak with unsafe_unretained prevents this property from becoming nil during Foo.dealloc
@property (nonatomic, weak) Foo *foo;

- (id)initWithFoo:(Foo *)foo;

@end

@interface Foo : NSObject

@property (nonatomic, strong) Bar *bar;

- (void)startObserving;
- (void)endObserving;

@end

@implementation Bar

- (id)initWithFoo:(Foo *)foo {
    if ((self = [super init])) {
        self.foo = foo;

        //Start observing
        [self.foo startObserving];
    }
    return self;
}

- (void)dealloc {
    //Since foo is a weak property, self.foo may actually be nil at this point! See dealloc of class Foo.
    [self.foo endObserving];
}

@end

@implementation Foo

- (id)init {
    if ((self = [super init])) {
        self.bar = [[Bar alloc] initWithFoo:self];
    }
    return self;
}

- (void)dealloc {
    //This will trigger the deallocation of bar. However, at this point all weak references to self will return nil already!
    self.bar = nil;

    //endObserving is never called, because Bar.foo reference was already nil.
}

- (void)startObserving {
    NSLog(@"Start observing");
}

- (void)endObserving {
    NSLog(@"End observing");
}

@end