dealloc是否会调用属性的setter来使它们无效?

时间:2013-09-14 07:50:24

标签: ios memory-management setter

当iOS内存管理解除分配给定对象时,解除分配的过程是否会通过setter方法找到它可能具有的任何属性的实例变量?

2 个答案:

答案 0 :(得分:3)

没有。我们可以通过以下程序验证这一点:

#import <Foundation/Foundation.h>


@interface CVObject :  NSObject

@property (nonatomic) NSNumber *number;

@end


@implementation CVObject

- (void)setNumber:(NSNumber *)number
{
    NSLog(@"setting number to %@", number);
    _number = number;
}

- (void)dealloc
{
    NSLog(@"deallocating");
}

@end


void doSomething()
{
    CVObject *object = [[CVObject alloc] init];
    object.number = @3;
}


int main(int argc, const char * argv[])
{
    @autoreleasepool {
        doSomething();
    }
    return 0;
}

运行时的输出是:

setting number to 3 
deallocating

通过向类中添加另一个类型CVObject*的属性,并在dealloc中放置断点,我们可以在第二个对象的释放时观察堆栈跟踪:

* thread #1: tid = 0x2203, 0x0000000100001a77 DoesDeallocUseProperties`-[CVObject dealloc](self=0x0000000102501da0, _cmd=0x00007fff934f508b) + 23 at main.m:36, stop reason = breakpoint 1.1
    frame #0: 0x0000000100001a77 DoesDeallocUseProperties`-[CVObject dealloc](self=0x0000000102501da0, _cmd=0x00007fff934f508b) + 23 at main.m:36
    frame #1: 0x0000000100001b4a DoesDeallocUseProperties`-[CVObject .cxx_destruct](self=0x0000000100103510, _cmd=0x000f6a00000f6a00) + 90 at main.m:20
    frame #2: 0x00007fff90030fcc libobjc.A.dylib`object_cxxDestructFromClass(objc_object*, objc_class*) + 100
    frame #3: 0x00007fff9002a922 libobjc.A.dylib`objc_destructInstance + 91
    frame #4: 0x00007fff9002afa0 libobjc.A.dylib`object_dispose + 22
    frame #5: 0x0000000100001aa4 DoesDeallocUseProperties`-[CVObject dealloc](self=0x0000000100103510, _cmd=0x00007fff934f508b) + 68 at main.m:37
    frame #6: 0x0000000100001c5c DoesDeallocUseProperties`doSomething + 268 at main.m:48
    frame #7: 0x0000000100001c94 DoesDeallocUseProperties`main(argc=1, argv=0x00007fff5fbffa80) + 36 at main.m:54
    frame #8: 0x00007fff951997e1 libdyld.dylib`start + 1

从迹线中可以清楚地看出,没有使用属性设置器或吸气剂。

现在,为什么会这样呢?重要的是要理解属性和实例变量没有固有的联系。名称可以独立变化。例如,拥有一个名为name的属性和一个实例变量_name是完全合法的,并且实现name的实际上没有触及实例变量{{1}的setter和访问器}}。如果ARC依赖于属性,这种情况将是灾难性的。

答案 1 :(得分:1)

不,它简单地向所有实例变量发送一条释放消息。

这可以通过一个简单的测试来观察,假设myProp是一个强大的属性:

-(void)dealloc
{
    NSLog(@"deallocing");
}

-(void)setMyProp:(MyClass *)prop
{
    NSLog(@"setting my prop: %@", prop);
}

您将看到由于重新分配而未调用setMyProp:方法。

理论上,您可以从被覆盖的setMyProp:方法中手动调用dealloc,但建议您谨慎使用:Calling a method on self while in dealloc