I am learning Objective-C and using the Big Nerd Ranch’s Obj-C book to familiarize myself with the language. Everything is going good so far until I reach this one exercise where I am supposed to create 2 classes where each of them inherits the dealloc method. The goal to show when an object actually gets deallocated. So the new dealloc looks like
Asset.h
#import <Foundation/Foundation.h>
@class Employee;
@interface Asset : NSObject{
NSString * label;
unsigned int resaleValue;
}
@property (strong) NSString * label;
@property unsigned int resaleValue;
@end
Employee.h
#import "Person.h"
@class Asset;
@interface Employee : Person
{
int employeeID;
NSString * lastName;
Person * spouse;
NSMutableArray * children;
NSMutableArray * assets;
}
@property int employeeID;
- (void) addAssetObject: (Asset *) a;
- (unsigned int) valueOfAssets;
@end
Implementations
@implementation Employee
//omitted
-(void) dealloc
{
NSLog(@"deallocating %@", self);
}
@end
@implementation Asset
//omitted
-(void) dealloc
{
NSLog(@"deallocating %@", self);
}
@end
main.m
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableArray * employees = [[NSMutableArray alloc] init];
for(int i = 0; i< 10; i++){
Employee * person = [[Employee alloc] init];
[person setWeightInKilos:90+i];
[person setHeightInMeters:1.8 - i/10.0];
[person setEmployeeID:i];
[employees addObject:person];
}
for(int i = 0; i< 10; i++){
Asset * asset = [[Asset alloc] init];
NSString * currentLabel = [NSString stringWithFormat:@"Laptop %d", i];
[asset setLabel:currentLabel];
[asset setResaleValue:i*17];
NSUInteger * randomIndex = random() % [employees count];
Employee * randomEmployee = [employees objectAtIndex:randomIndex];
[randomEmployee addAssetObject:asset];
}
NSLog(@"Employees: %@", employees);
NSLog(@"Giving up ownership of one employee");
[employees removeObjectAtIndex:5]; // This is supposed to trigger the deallocate method
NSLog(@"Giving up ownership of array");
employees = nil;
}
return 0;
}
Of course description is already inherited so that %@would work. However, when I ran it. The dealloc is not getting called and I am not getting the print outs that deallocates the object. I am not sure what I am doing wrong here.
Sidenote: Shouldn’t the dealloc do [super dealloc] as well?
From reading your code, I believe you’re using Automatic Reference Counting (ARC). If you’re not, you should start. (ARC is the new default, Apple’s recommendation, and clearly the future.)
You have a circular reference: Your employee has an array of assets, which results in the assets being held in existence by the employee. Meanwhile each asset contains a strong reference to the owning holder employee. This means neither object can ever be released.
To fix this, convert the reference from the asset back to the holding Employee to be a weak reference.
Without this fix:
With this fix: