【发布时间】:2013-02-28 21:45:16
【问题描述】:
使用 ARC 和 iOS 6.1,我在这里有一个简单的类来演示我的问题:
#import <GHUnitIOS/GHUnit.h>
@interface MyClass : NSObject
@property BOOL cancel;
@property BOOL dead;
-(void)doSomething;
-(void)reset;
-(void)logMe;
@end
@implementation MyClass
-(id)init {
self = [super init];
if(self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reset) name:@"dude" object:nil];
NSLog(@"I'm alive");
}
return self;
}
-(void)dealloc {
_dead = YES;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[MyClass cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"I'm dead");
}
-(void)doSomething {
NSLog(@"dude:%d", _dead);
if(!_cancel) {
[self performSelector:@selector(doSomething) withObject:nil afterDelay:0.2];
NSLog(@"scheduled");
}
[self logMe];
}
-(void)reset {
NSLog(@"reset");
[MyClass cancelPreviousPerformRequestsWithTarget:self];
_cancel = YES;
[self doSomething];
}
-(void)logMe {
NSLog(@"logme");
}
@end
@interface ATest : GHTestCase
@end
@implementation ATest
-(BOOL)shouldRunOnMainThread {return YES;}
-(void)setUpClass {}
-(void)tearDownClass {}
-(void)setUp {}
-(void)tearDown {}
-(void)testBlah {
MyClass* blah = [[MyClass alloc] init];
[blah doSomething];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void){
[[NSNotificationCenter defaultCenter] postNotificationName:@"dude" object:nil];
});
blah = nil;
}
@end
在测试中,MyClass 被实例化,我启动 doSomething,它会执行一些工作(即记录),然后如果 _cancel 为假,则在 0.25 秒后调用自身。同时,我安排在 1.0 秒后触发通知(最终将 _cancel 设置为 true)。然后我将blah 归零。
所以我的期望是performSelector:withObject:withDelay 创建的计时器拥有对MyClass 的引用。
但是,当我在启用僵尸的情况下运行此测试时,我会得到以下输出:
2013-02-28 15:30:55.518 测试[11946:c07] ATest/testBlah
2013-02-28 15:30:56.789 测试[11946:c07] 重新运行:ATest/testBlah
2013-02-28 15:30:56.790 测试[11946:c07] 我还活着
2013-02-28 15:30:56.790 测试[11946:c07] 老兄:0
2013-02-28 15:30:56.791 测试[11946:c07] 已安排
2013-02-28 15:30:56.791 测试[11946:c07] logme
2013-02-28 15:30:56.792 测试[11946:c07] ATest/testBlah ✔ 0.00s
2013-02-28 15:30:56.991 测试[11946:c07] 老兄:0
2013-02-28 15:30:56.992 测试[11946:c07] 已安排
2013-02-28 15:30:56.992 测试[11946:c07] logme
2013-02-28 15:30:57.193 测试[11946:c07] 老兄:0
2013-02-28 15:30:57.194 测试[11946:c07] 已安排
2013-02-28 15:30:57.194 测试[11946:c07] logme
2013-02-28 15:30:57.395 测试[11946:c07] 老兄:0
2013-02-28 15:30:57.395 测试[11946:c07] 已安排
2013-02-28 15:30:57.396 测试[11946:c07] logme
2013-02-28 15:30:57.596 测试[11946:c07] 老兄:0
2013-02-28 15:30:57.597 测试[11946:c07] 已安排
2013-02-28 15:30:57.597 测试[11946:c07] logme
2013-02-28 15:30:57.792 测试[11946:c07] 重置
2013-02-28 15:30:57.793 测试[11946:c07] 我死了
2013-02-28 15:30:57.793 测试[11946:c07] * -[MyClass doSomething]:消息发送到已释放实例 0xb584880
我在reset 方法中调用cancelPreviousPerformRequestsWithTarget: 后,为什么self 被释放?
这个问题是 ARC 问题还是编码错误?
【问题讨论】:
标签: objective-c automatic-ref-counting selector