ARC, Blocks and Retain Cycles

后端 未结 2 1260
清歌不尽
清歌不尽 2020-12-03 02:38

Working on an iOS project that targets 4.0 and 5.0, using ARC.

Running into an issue related to blocks, ARC and referencing an object from outside the block. Here\'s

2条回答
  •  天涯浪人
    2020-12-03 03:28

    This appears to be the problem described by Conrad Stoll in Blocks, Operations, and Retain Cycles, but his writeup misses a few important points:

    • __block looks like the Apple-recommended way of avoiding a strong reference to captured variables in MRC mode but is completely unnecessary in ARC mode. In this case, it is completely unnecessary in ARC mode; it is also unnecessary in MRC mode though the lighter-weight workaround is much more verbose: void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; }
    • In ARC mode, you need both a strong reference (so you can add it to the queue) and a weak/unsafe_unretained reference

    The simplest solution looks like this:

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    AFHTTPRequestOperation * __unsafe_unretained unretainedOperation = operation;
    
    [operation setCompletionBlock:^ {
      if ([unretainedOperation isCancelled]) {
        return;
      }
      ... do stuff ...
    }];
    

    Even if you break the reference cycle, there is no reason for the Block to retain the AFHTTPRequestOperation in the first place (assuming the operation keeps itself alive until the completion handler completes, which isn't always guaranteed but is generally true and assumed by ARC if it is referred to using self further up the call stack).

    The best fix appears to be to update to the latest AFNetworking, which passes the operation into the block as an argument.

提交回复
热议问题