挂钩结束ARC dealloc

鉴于以下简单的实现:

@implementation RTUDeallocLogger -(void)dealloc { NSLog(@"deallocated"); } @end 

我们在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 

我们得到以下日志输出:

归零
完成归零
重新分配的
重新分配的
重新分配的

在所有释放完成后,我想执行一个操作。 这可能吗?

这个问题的目的是真正理解ARC的机制,特别是ARC在什么时候触发这些释放,以及当我放弃引用时是否会同步发生。

-dealloc总是同步的,并且当最后的强引用被移除时发生。 在你的代码的情况下,+ arrayWithObjects:很可能(如果至less编译-O0)将数组放在autorelease池中,所以最后一个强引用在池被排空时被移除,而不是当你设置variables为NULL (你应该使用nil作为ObjC对象,顺便说一句)。

你可以避免使用alloc / init来创build自动释放池中的对象,并且你可以通过编译优化来避免它(实现细节bla bla)。 你也可以使用@autoreleasepool {}来引入一个内部池,并以这种方式限制生命周期。

如果我是苹果的工程师,我可能会争辩说,你的问题可能是你的devise。 几乎没有理由要通过观看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"); } 

我假设你可以将你感兴趣的所有对象的生命周期与单个容器的生命周期相关联; 否则你可以把通告者和所有相关的对象关联起来。

当你得到arrayDidDealloc时,数组肯定已经arrayDidDealloc

ARC在什么时候触发这些释放

ARC基于静态分析将分配/解除分配插入到您的代码中。 您可以通过查看源代码的组合来查看它在哪里执行此操作 – 转至Product -> Generate Output在Xcode中Product -> Generate Output

当我删除引用时是否会同步发生

保留/释放/自动释放总是同步的。

你的代码

 arr = [NSArray arrayWithObjects:[[RTUDeallocLogger alloc] init], [[RTUDeallocLogger alloc] init], [[RTUDeallocLogger alloc] init], nil]; 

将隐式地将对象放置到自动释放池中。 对象分配后,你不希望它被保留(因为NSArray一旦接收到对象将执行保留),但不能立即释放它,否则它将永远不会使它活着的NSArray。 这是autorelease的目的 – 以涵盖两个所有者之间的对象将会陷入僵局的情况。

在alloc时间的保留计数是1,然后它由autoreleasepool保留并由你释放,所以保留计数保持为1.然后,由NSArray保留,所以保留计数变为2。

之后,NSArray被释放,所以保留计数返回到1,当autorelease池有机会运行时,对象最终被清理。

通过嵌套另一个池,可以使autorelease行为更快 – 通过用@autorelease {}子句包装您的NSArray创build。