Pierre Bernard

My little hideout on the net

Automatically releasing retained @property values

I subscribe to the opinion, that setters should not be called in constructors nor in destructors. This negates some of the benefits of @synthesize accessors. Indeed, one needs to keep the dealloc method in sync with the setter semantics. Our dealloc methods thus look like this:

- (void)dealloc
{
// Retained properties
[_firstProperty
release], _firstProperty = nil;
[_thirdProperty
release], _thirdProperty = nil;

// Assigned properties
secondProperty =
nil;

[
super dealloc];
}

This is repetitive and error-prone. Luckily, we may generate @synthesize instructions as well as destructors.

The alternative, is to use introspection to dynamically determine how the various properties need to be freed. For this, I suggest a category on NSObject:

@implementation NSObject (PropertyDealloc)

- (
void)deallocProperties
{
Class class = [self class];
unsigned int pCount;
objc_property_t *properties = class_copyPropertyList(class, &pCount);

for (unsigned int i = 0; i < pCount; i++) {
objc_property_t property = properties[i];
NSString *propertyAttributes = [[[NSString alloc] initWithUTF8String:property_getAttributes(property)] autorelease];
NSArray *propertyAttributeArray = [propertyAttributes componentsSeparatedByString:@","];
BOOL isRetained = NO;

for (NSString *string in propertyAttributeArray) {
isRetained = isRetained || [string
isEqual:@"&"] || [string isEqual:@"C"];
}

if (isRetained) {
NSString *variableName = nil;
NSString *lastProperty = (NSString*)[propertyAttributeArray lastObject];

if ([lastProperty hasPrefix:@"V"]) {
variableName = [lastProperty
substringFromIndex:1];
}

if (variableName != nil) {
Ivar ivar = class_getInstanceVariable(class, [variableName UTF8String]);
id value = object_getIvar(self, ivar);

object_setIvar(self, ivar, nil);
[value
release];
}
}
}

free(properties);
}

@end

Usage is extremely simple:

- (void)dealloc
{
[
self deallocProperties];

[
super dealloc];
}

This post was inspired by Vincent Gable.
Comments (3)