Last active
August 29, 2015 14:09
-
-
Save epatey/02d8ca2b1e8593a6ce7a to your computer and use it in GitHub Desktop.
NSObject category that explodes if an object doesn't get deallocated soon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Use this gist when you need to assert that a particular object is deallocated | |
// "soon". I use this technique extensively to ensure that I don't introduce retain | |
// cycles into my code. It really beats not noticing that you regressed and started | |
// leaking a view controller months ago! | |
@interface NSObject (ExplodingDealloc) | |
// Explode if this object isn't deallocated within 3 seconds | |
- (void)explodeIfNoDealloc; | |
// Return a signal that will explode if the object isn't deallocated within | |
// 3 seconds of subscription. | |
- (RACSignal *)explodingDeallocSignalWithTimeout:(NSTimeInterval)expiration; | |
@end | |
@implementation NSObject (ExplodingDealloc) | |
- (void)explodeIfNoDealloc { | |
[[self explodingDeallocSignalWithTimeout:3] subscribeCompleted:^{}]; | |
} | |
- (RACSignal *)explodingDeallocSignalWithTimeout:(NSTimeInterval)expiration { | |
NSString *description = self.description; | |
return [[[self.rac_willDeallocSignal | |
timeout:expiration onScheduler:[RACScheduler mainThreadScheduler]] | |
doCompleted:^{ | |
NSLog(@"explodingDeallocSignal - %@ did dealloc", description); | |
}] | |
doError:^(NSError *error) { | |
NSAssert(NO, @"explodingDeallocSignal - %@ not deallocated", description); | |
}]; | |
} | |
// If you're not using ReactiveCocoa, you're living half a life. Nevertheless, | |
// here's a version for you. | |
- (void)nonRACVersion { | |
NSString *description = self.description; | |
__weak NSObject *weakSelf = self; | |
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ | |
NSObject *strongSelf = weakSelf; | |
if (strongSelf) { | |
NSAssert(NO, @"explodeIfNoDealloc - %@ not deallocated", description); | |
} | |
else { | |
NSLog(@"explodeIfNoDealloc - %@ did dealloc", description); | |
} | |
}); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice idea. However, both versions always explode even on the simplest
[[NSObject new] explode]
(wrapped in a method call, which means that the new object should be deallocated). In all places I tried it, the use ofexplode
actually prevented deallocation, even on objects which where deallocated without it. However, I don't have an explanation for that yet - unfortunately.A second remark: I would strongly suggest to wrap the invocation in something like
saves you a lot of boilerplate code you don't really want to have in your archives - or do you ;) ?