Skip to content

Instantly share code, notes, and snippets.

@fpillet
Created January 6, 2010 13:18
Show Gist options
  • Save fpillet/270266 to your computer and use it in GitHub Desktop.
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
/* 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