15

我知道 的定义unsafe_unretained

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

我想通过示例了解它的用途,以及它如何与内存管理一起使用。

4

3 回答 3

39

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

weak属性类似于unsafe_unretained,只是它们工作得更聪明一些。当分配给该属性的对象被释放时,弱引用自动变为nil,以避免在向该对象(其内存地址)发送消息时崩溃。

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

那么为什么要使用unsafe_unretained而不是weak呢?弱引用仅适用于 iOS 5 及更高版本,因此如果您正在构建面向 iOS 4 的 ARC 应用程序,则需要使用unsafe_unretained属性。同样,向已发布的属性发送消息并不是您希望在任何代码中拥有的任何东西。如果您的代码组织良好,那么您应该对此没有任何问题。

于 2013-04-12T17:45:47.210 回答
2

在 ARC 之前,人们可能会指定一个委托或其他对父属性的引用,assign以防止保留循环。随着 ARC 和较新的编译器的引入,您将改为使用unsafe_unretained.

因此,您可以在不需要引用所有权的任何时候使用它,并且当您不需要或不想使用新的weak引用类型时(当引用被释放时它会取消引用)。

于 2013-04-12T10:26:59.857 回答
0

这是 unsafe_unretained 的一个特定用例。假设两个类相互引用,一个方向强,另一个方向弱。在第一个类的释放期间,第二个类对它的弱引用已经为零,从而阻止了适当的清理。用 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
于 2017-10-27T13:41:52.743 回答