What is the use of unsafe_unretained attribute?

后端 未结 3 1041
忘了有多久
忘了有多久 2021-02-05 18:31

I know the definition of unsafe_unretained.

So i don\'t expect anyone to write its definition.

I want to know its use with example, and how it wor

相关标签:
3条回答
  • 2021-02-05 18:59

    Here is a specific use case for unsafe_unretained. Say two classes reference each other, one direction being strong and the other direction weak. During dealloc of the first class the weak reference to it from the second class will already be nil, preventing proper cleanup to take place. Replacing the weak reference with an unsafe_unretained reference will solve this issue. See the code sample below:

    @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
    
    0 讨论(0)
  • 2021-02-05 19:06

    Previously to ARC, one might specify a delegate or other reference-to-parent property as assign to prevent retain cycles. With the introduction of ARC and the newer compilers you would instead use unsafe_unretained.

    So you use it any time you do not need ownership of the reference, and when you don't need or want to use the new weak reference type (which nulls out the reference when it is deallocated).

    0 讨论(0)
  • 2021-02-05 19:09

    unsafe_unretained only exists in ARC (Automatic Reference Counting). It works like assign in MRC (Manual Reference Counting). These properties won't be retained. Usually, you'd want to use such properties for delegates, because they don't need an owner which retains them.

    weak properties are like unsafe_unretained, except that they work a bit smarter. When the object assigned to the property is released, a weak reference automatically becomes nil, to avoid crashes when sending messages to that object (its memory address).

    unsafe_unretained properties don't do this. They will always hold on to the memory address (unless you manually change it) assigned to it, regardless of the object associated to that address. Weak references can prevent crashes in such a case, but the result still won't be as expected. If your code is organized and well-written, this shouldn't happen.

    So why would you use unsafe_unretained instead of weak? Weak references are only available on iOS 5 and higher, so if you're building an ARC app targeting iOS 4, you need to use unsafe_unretained properties. And again, sending messages to a released property isn't anything you want to have in any code. If your code is well organized then you shouldn't have any problems with this.

    0 讨论(0)
提交回复
热议问题