Skip to content

Instantly share code, notes, and snippets.

@an0
Created November 4, 2016 19:38
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save an0/934e9b2b494a5b1425e2f41ef38b0293 to your computer and use it in GitHub Desktop.
When weak is safer than strong

http://clang.llvm.org/docs/AutomaticReferenceCounting.html#self:

The self parameter variable of an Objective-C method is never actually retained by the implementation.

But http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics:

For __weak objects, the current pointee is retained and then released at the end of the current full-expression. This must execute atomically with respect to assignments and to the final release of the pointee. For all other objects, the lvalue is loaded with primitive semantics.

The whole scheme makes weak references safer then strong references sometimes:

__block NSArray *strongArray = @[@1, @2];
__weak NSArray *weakArray = strongArray;
[weakArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"%p: %@", weakArray, obj);
    strongArray = nil;
}];
    
strongArray = @[@1, @2];
// It will crash.
[strongArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"%p: %@", strongArray, obj);
    strongArray = nil;
}];

This reversed safety only occurs for Objective-C, not Swift:

var strongArray: NSArray? = [1, 2]
weak var weakArray = strongArray
weakArray?.enumerateObjects({ (obj, idx, stop) in
    print(weakArray, obj)
    strongArray = nil
})

strongArray = [1, 2]
// It won't crash.
strongArray?.enumerateObjects({ (obj, idx, stop) in
    print(strongArray, obj)
    strongArray = nil
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment