Objective-C:dealloc没有被调用

时间:2012-04-24 16:37:36

标签: objective-c

我正在学习Objective-C并使用Big Nerd Ranch的Obj-C书来熟悉这门语言。到目前为止,一切都很顺利,直到我达到这个练习,我应该创建2个类,每个类都继承dealloc方法。显示对象实际被解除分配的目标。所以新的dealloc看起来像

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

实现

@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;
}

当然description已经被继承,因此%@可以正常工作。但是,当我跑它。 dealloc没有被调用,我没有得到解除分配对象的打印输出。我不确定我在这里做错了什么。

旁注:dealloc不应该[super dealloc]吗?

1 个答案:

答案 0 :(得分:9)

通过阅读您的代码,我相信您正在使用自动引用计数(ARC)。如果你不是,你应该开始。 (ARC是新的默认设置,Apple的推荐,显然是未来。)

您有一个循环引用:您的员工拥有一系列资产,这导致员工保留资产。同时,每个资产都包含对拥有持有人员工的强烈参考。这意味着任何对象都无法释放。

要解决此问题,请将资产中的引用转换回持有的Employee作为引用。

@interface Asset : NSObject{
    NSString * label;
    __weak Employee * holder;
    unsigned int resaleValue;
}

没有这个修复:

  • 员工将资产保存在内存中。
  • 资产将员工留在记忆中。
  • 即使对员工和资产的所有其他引用都消失了,它们也会继续相互记忆。

使用此修复程序:

  • 员工将资产保存在内存中。
  • 资产将员工留在记忆中。相反,它们包含一个安全的归零参考。
  • 当不再需要其他任何东西时,员工将被释放。
  • 当员工被释放时,持有人实例变量将被“神奇地”清除。
  • 由于不再引用资产,它们也会通过。