Skip to content

Instantly share code, notes, and snippets.

@beccadax
Last active December 18, 2015 12:59
Show Gist options
  • Save beccadax/5787175 to your computer and use it in GitHub Desktop.
Save beccadax/5787175 to your computer and use it in GitHub Desktop.
Allows you to add a "vulture": a block that will be executed when the object it's attached to is deallocated.
#import <Foundation/Foundation.h>
@interface NSObject (addVulture)
// Do NOT use a block that captures this object.
// If you capture it strongly, you'll create a retain cycle.
// If you capture it weakly, you'll just get nil.
// If you capture it unsafely, you'll start calling methods on a mostly-dealloced object!
- (void)addVultureWithBlock:(dispatch_block_t)block;
@end
#import "ArchVulture.h"
#import <objc/runtime.h>
@interface ArchVulture: NSObject
- (id)initWithBlock:(dispatch_block_t)block nextVulture:(ArchVulture*)nextVulture;
@property (copy) dispatch_block_t block;
@property (strong) ArchVulture * nextVulture;
@end
@implementation ArchVulture
- (id)initWithBlock:(dispatch_block_t)block nextVulture:(ArchVulture*)nextVulture {
if((self = [super init])) {
_block = [block copy];
_nextVulture = nextVulture;
}
return self;
}
- (void)dealloc {
_block();
}
@end
@implementation NSObject (addVulture)
- (void)addVultureWithBlock:(dispatch_block_t)block {
// Make sure our ArchVulture objects aren't put in the parent autorelease pool,
// giving them a longer lifetime than intended.
@autoreleasepool {
ArchVulture * currentVulture = objc_getAssociatedObject(self, _cmd);
ArchVulture * newVulture = [[ArchVulture alloc] initWithBlock:block nextVulture:currentVulture];
objc_setAssociatedObject(self, _cmd, newVulture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
}
@end
#import "ArchVulture.h"
int main(int argc, char *argv[]) {
@autoreleasepool {
NSObject * owner = [NSObject new];
[owner addVultureWithBlock:^{
NSLog(@"He's dead, Jim!");
}];
owner = nil;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment