1

我正在学习 Objective-C 并使用 Big Nerd Ranch 的 Obj-C 书来熟悉该语言。到目前为止一切都很好,直到我完成了这个练习,我应该在其中创建 2 个类,其中每个类都继承了该dealloc方法。显示对象何时真正被释放的目标。所以新的 dealloc 看起来像

资产.h

#import <Foundation/Foundation.h>
@class Employee;

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

@property (strong) NSString * label;
@property unsigned int resaleValue;

@end

员工.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

主文件

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]吗?

4

1 回答 1

9

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

您有一个循环引用:您的员工拥有一系列资产,这导致资产由员工持有。同时,每项资产都包含对拥有者员工的强烈引用。这意味着任何一个对象都不能被释放。

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

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

没有这个修复:

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

有了这个修复:

  • 员工在内存中持有资产。
  • 资产不会在内存中保存员工。相反,它们包含一个安全的归零参考。
  • 当其他任何事情不再需要时,该员工将被释放。
  • 当员工被释放时,持有者实例变量将被“神奇地”清除。
  • 由于不再引用资产,因此它们也将通过。
于 2012-04-24T16:58:45.230 回答