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
。これは何らかの作業 (ログ記録など) を実行し、0.25 秒後に_cancel
が false の場合は自身を呼び出します。その間、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 ] 私は生きている
02-28 15:30:56.791 Tests[11946:c07] logme
2013-02-28 15:30:56.792 Tests[11946:c07] ATest/testBlah ✔ 0.00s
2013-02-28 15:30:56.991 Tests[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 Tests [ 11946
: c07 ] 私は死んだ
メソッドself
を呼び出しcancelPreviousPerformRequestsWithTarget:
た後に割り当てが解除されるのはなぜですか?reset
この問題は ARC の問題ですか、それともコーディング エラーですか?