jverkoey/nimbus — pull request #146 by gurgeous (2012-01-23 19:18:12+00:00)
Title: NIOperation blocks need to be nilled out on dealloc

The blocks in NIOperation need to be set to nil on dealloc. This is true with ARC, not sure about master. Here's a simple test case that illustrates the problem:

```objc
// this class logs when deallocated
@interface NoisyObj : NSObject
@end
@implementation NoisyObj
- (void)dealloc
{
NSLog(@"NoisyObj dealloc");
}
@end

// logs when deallocated, and can nil out self.didFinishBlock
@interface Op : NINetworkRequestOperation
@end

@implementation Op
- (void)dealloc
{
NSLog(@"Op dealloc");
// without this, NoisyObj will never be deallocated
// self.didFinishBlock = nil;
}
@end

// the actual test code
Op *op = [[Op alloc] initWithURL:[NSURL URLWithString:@"http://www.apple.com"]];
NoisyObj *usedInsideTheBlock = [[NoisyObj alloc] init];
op.didFinishBlock = ^() {
NSLog(@"didFinishBlock %@", usedInsideTheBlock);
};
[[Nimbus networkOperationQueue] addOperation:op];
```

If you run the test without niling out didFinishBlock, the output looks like this:

```
didFinishBlock
Op dealloc
```

Notice that the block (and therefore NoisyObj) were never deallocated. If you add the line that nils out didFinishBlock, you get this instead:

```
didFinishBlock
NoisyOp dealloc
NoisyObj dealloc
```

I think this is a side-effect of the (copy) block properties. Maybe ARC isn't smart enough to handle those for us. Anyway, this is a serious bug because if you use blocks in Nimbus operations all the objects referenced in those blocks will never be released. In my case that ends up being most of the app!