弱い参照とブロックについてはかなり理解できたと思っていましたが、以下のコード スニペットを試してみると、いくつか理解できないことがありました。
メソッドtest1 : すべて問題なく、オブジェクトは保持されません
メソッドtest2 : オブジェクトがメソッドtest3の最後まで保持されるように見える理由がわかりません! object = nil
メソッドtest2の最後に明示的に設定しても何も変わりません。
メソッドtest3 : オブジェクトは保持されません。メソッドtest2がこのように動作しないのはなぜですか?
副次的な質問として、弱い変数がスレッドセーフかどうか実際に疑問に思っていましたか? つまり、異なるスレッドから弱い変数にアクセスしようとしたときに BAD_ACCESS 例外が発生しない場合です。
@interface Object : NSObject
@property (nonatomic) NSInteger index;
@end
@implementation Object
- (id)initWithIndex:(NSInteger) index {
if (self = [super init]) {
_index = index;
}
return self;
}
- (void)dealloc {
NSLog(@"Deallocating object %d", _index);
}
@end
試験方法
- (void) test1 {
NSLog(@"test1");
Object* object = [[Object alloc] initWithIndex:1];
NSLog(@"Object: %@", object);
__weak Object* weakObject = object;
dispatch_async(dispatch_queue_create(NULL, NULL), ^{
//NSLog(@"Weak object: %@", weakObject);
[NSThread sleepForTimeInterval:2];
NSLog(@"Exiting dispatch");
});
[NSThread sleepForTimeInterval:1];
NSLog(@"Exiting method");
}
- (void) test2 {
NSLog(@"test2");
Object* object = [[Object alloc] initWithIndex:2];
NSLog(@"Object: %@", object);
__weak Object* weakObject = object;
dispatch_async(dispatch_queue_create(NULL, NULL), ^{
NSLog(@"Weak object: %@", weakObject);
[NSThread sleepForTimeInterval:2];
NSLog(@"Exiting dispatch");
});
[NSThread sleepForTimeInterval:1];
NSLog(@"Exiting method");
}
- (void) test3 {
NSLog(@"test3");
Object* object = [[Object alloc] initWithIndex:3];
NSLog(@"Object: %@", object);
NSValue *weakObject = [NSValue valueWithNonretainedObject:object];
dispatch_async(dispatch_queue_create(NULL, NULL), ^{
NSLog(@"Weak object: %@", [weakObject nonretainedObjectValue]);
[NSThread sleepForTimeInterval:2];
NSLog(@"Exiting dispatch");
});
[NSThread sleepForTimeInterval:1];
NSLog(@"Exiting method");
}
- (void) test {
[self test1];
[NSThread sleepForTimeInterval:3];
[self test2];
[NSThread sleepForTimeInterval:3];
[self test3];
}
上記の出力は次のとおりです。
2013-05-11 19:09:56.753 test[1628:c07] test1
2013-05-11 19:09:56.754 test[1628:c07] Object: <Object: 0x7565940>
2013-05-11 19:09:57.755 test[1628:c07] Exiting method
2013-05-11 19:09:57.756 test[1628:c07] Deallocating object 1
2013-05-11 19:09:58.759 test[1628:1503] Exiting dispatch
2013-05-11 19:10:00.758 test[1628:c07] test2
2013-05-11 19:10:00.758 test[1628:c07] Object: <Object: 0x71c8260>
2013-05-11 19:10:00.759 test[1628:1503] Weak object: <Object: 0x71c8260>
2013-05-11 19:10:01.760 test[1628:c07] Exiting method
2013-05-11 19:10:02.760 test[1628:1503] Exiting dispatch
2013-05-11 19:10:04.761 test[1628:c07] test3
2013-05-11 19:10:04.762 test[1628:c07] Object: <Object: 0x71825f0>
2013-05-11 19:10:04.763 test[1628:1503] Weak object: <Object: 0x71825f0>
2013-05-11 19:10:05.764 test[1628:c07] Exiting method
2013-05-11 19:10:05.764 test[1628:c07] Deallocating object 3
2013-05-11 19:10:05.767 test[1628:c07] Deallocating object 2
2013-05-11 19:10:06.764 test[1628:1503] Exiting dispatch