Created
January 6, 2010 13:18
-
-
Save fpillet/270266 to your computer and use it in GitHub Desktop.
A UIViewController subclass which automagically releases its UIView-derived instance variables upon -dealloc and -viewDidUnload
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
/* Base UIViewController subclass for your iPhone applications which automatically | |
* releases your instance variables pointing to UIView objects or UIView-subclassed objects, | |
* limiting the work you have to do in -dealloc and -viewDidUnload | |
* | |
* All you have to do is make your UIViewController subclasses inherit from BaseUIViewController | |
* instead of UIViewController | |
* | |
* The helper function that disposes of objects is generalized and can be used for other | |
* types of objects as well. | |
* | |
* Use this code ONLY if you understand what it does, and have correctly read the comments. | |
* | |
* Public domain code, (c) 2010 Florent Pillet ([email protected]) | |
*/ | |
/* BaseUIViewController.h */ | |
#import <UIKit/UIKit.h> | |
@interface BaseUIViewController : UIViewController | |
{ | |
} | |
@end | |
/* BaseUIViewController.m */ | |
#import <objc/runtime.h> | |
#import "BaseUIViewController.h" | |
@interface BaseUIViewController () | |
- (void)releaseOutlets; | |
@end | |
// Prototype for the helper function | |
void ReleaseInstanceVariablesDerivingFrom(Class ivarBaseClass, id object, Class objectBaseClass); | |
@implementation BaseUIViewController | |
- (void)dealloc | |
{ | |
[self releaseOutlets]; | |
[super dealloc]; | |
} | |
- (void)viewDidUnload | |
{ | |
[self releaseOutlets]; | |
[super viewDidUnload]; | |
} | |
- (void)releaseOutlets | |
{ | |
// Release all instance variables that are subclasses of UIView in this object | |
// and it objects deriving from ourselves. | |
ReleaseInstanceVariablesDerivingFrom([UIView class], self, [UIViewController class]); | |
} | |
@end | |
void ReleaseInstanceVariablesDerivingFrom(Class ivarBaseClass, id object, Class objectBaseClass) | |
{ | |
// Release all instance variables of an object that derive from UIView. | |
// Only process the instance and parent classes, up to the first "inheritedFrameworkClass" | |
// i.e. if you have a UIViewController subclass, you should call this with: | |
// | |
// ReleaseInstanceVariablesDerivingFrom([UIView class], self, [UIViewController class]); | |
// | |
// Note, though, that all ivars which don't derive from the base class (here, UIView) | |
// MUST be nil'd before calling this function, otherwise bad things™ will ensue. | |
Class objectClass = [object class]; | |
while (objectClass && objectClass != objectBaseClass) | |
{ | |
unsigned int count = 0; | |
Ivar *ivars = class_copyIvarList(objectClass, &count); | |
if (ivars != NULL) | |
{ | |
Ivar *ip = ivars; | |
for (unsigned int i = 0; i < count; i++, ip++) | |
{ | |
const char *type = ivar_getTypeEncoding(*ip); | |
if (type[0] == '@' && type[1] == '"') | |
{ | |
id value = object_getIvar(object, *ip); | |
if ([value isKindOfClass:ivarBaseClass]) | |
{ | |
#ifdef DEBUG | |
NSLog(@"-> releasing ivar %s value %p of type %s of class %@, retainCount=%u", ivar_getName(*ip), value, type, [value class], [value retainCount]); | |
#endif | |
[value release]; | |
object_setIvar(object, *ip, nil); | |
break; | |
} | |
} | |
} | |
free(ivars); | |
} | |
objectClass = class_getSuperclass(objectClass); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment