挂钩结束ARC dealloc

spe*_*der 2 objective-c dealloc ios automatic-ref-counting

鉴于以下简单实现:

@implementation RTUDeallocLogger
-(void)dealloc
{
    NSLog(@"deallocated");
}
@end
Run Code Online (Sandbox Code Playgroud)

我们在ARC下运行以下代码:

@implementation RTURunner
{
    NSArray* arr;
}
-(void)run{
    arr = [NSArray
           arrayWithObjects:[[RTUDeallocLogger alloc]init],
                            [[RTUDeallocLogger alloc]init],
                            [[RTUDeallocLogger alloc]init],
                            nil];
    NSLog(@"nulling arr");
    arr = NULL;
    NSLog(@"finished nulling");
}
@end
Run Code Online (Sandbox Code Playgroud)

我们得到以下日志输出:

nulling arr
finished nulling
deallocated
deallocated
deallocated

所有解除分配完成后我想执行一个动作.这可能吗?

这个问题的目的是为了更多地了解ARC的机制,特别是ARC在什么时候触发这些解除分配,以及当我删除引用时这是否会同步发生.

Cat*_*Man 6

-dealloc始终是同步的,并在删除最后一个强引用时发生.在您的代码的情况下,+ arrayWithObjects:很可能(如果至少在-O0编译)将数组放入自动释放池中,因此当池耗尽时,最后一个强引用将被删除,而不是在您将变量设置为NULL时(你应该使用nil作为ObjC对象,顺便说一句).

您可以通过使用alloc/init创建来避免在自动释放池中拥有该对象,并且您可以(实现细节,bla bla)通过打开优化进行编译来避免它.您还可以使用@autoreleasepool {}来引入内部池并以此方式绑定生命周期.

  • @spender ......对那个更好的问题的答案是"@autoreleasepool". (3认同)

Tom*_*mmy 6

如果我是Apple的工程师,我可能会说你的问题可能就是你的设计.你几乎没有理由想通过观察dealloc而不是dealloc自己采取行动来有效行动.

[一个巨大的编辑如下:弱属性不通过正常的属性机制,因此它们不符合KVO,包括最初提出的内部隐式KVO]

也就是说,你可以做的是通过对象关联将两个对象的生命周期绑定在一起,并使用后者的dealloc作为前者dealloc的调用.

所以,例如

#import <objc/runtime.h>

@interface DeallocNotifier;
- (id)initWithObject:(id)object target:(id)target action:(SEL)action;
@end

@implementation DeallocNotifier
- (id)initWithObject:(id)object target:(id)target action:(SEL)action
{
    ... blah ...

    // we'll use a static int even though we'll never access by this key again
    // to definitely ensure no potential collisions from lazy patterns
    static int anyOldKeyWellNeverUseAgain;

    objc_setAssociatedObject(object, &anyOldKeyWellNeverUseAgain, self, OBJC_ASSOCIATION_RETAIN);

    ... blah ...
}
- (void)dealloc
{
    [_target performSelector:_action];
}
@end

-(void)run{
    arr = ...

    [[DeallocNotifier alloc]
           initWithObject:arr target:self action:@selector(arrayDidDealloc)];

    /* you may not even need *arr in this case; I'm unclear as
    to why you have an instance variable for something you don't
    want to keep, so I guess it'll depend on your code */
} // end of run


- (void)arrayDidDealloc
{
    NSLog(@"array was deallocated");
}
Run Code Online (Sandbox Code Playgroud)

我假设您能够将您感兴趣的所有对象的生命周期与单个容器的生命周期联系起来; 否则您可以将通知程序与所有相关对象相关联.

阵列肯定已经消失了arrayDidDealloc.