ここでの問題は、インスタンス化するブロックを実行していないように見えることですmyObject
。説明のために、この小さなプログラムを実行します。
#import <Foundation/Foundation.h>
typedef void(^MyTestBlock)(void);
@interface Foo:NSObject
- (id)initWithBlock:(MyTestBlock)aBlock;
- (void)someMethod;
@end
@implementation Foo {
MyTestBlock _block;
}
- (id)initWithBlock:(MyTestBlock)aBlock {
self = [super init];
if( !self ) { return nil; }
_block = aBlock;
return self;
}
- (void)someMethod {
_block();
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
__block NSObject *myObject;
Foo *myFoo = [[Foo alloc] initWithBlock:^{
myObject = [[NSObject alloc] init];
}];
[myFoo someMethod];
NSLog((myObject)?@"Your object was created":@"Why is my object nil?");
}
}
これ2012-11-26 05:00:58.519 Untitled 2[23467:707] Your object was created
はコンソールに出力されます。重要なのは、ブロックはそれ自体では実行されないということです。上記のコードでは、ブロックをクラスのivarとして設定していますが、を呼び出すまで実行しませsomeMethod
んFoo
。
編集:
質問を編集すると、メインキューに送信された非同期ディスパッチブロックのコンテキストでブロックが実行されないことが示されます。これがコマンドラインアプリケーションの場合はdispatch_main()
、の最後で呼び出す必要がありますmain
。man
のページを参照してくださいdispatch_get_main_queue()
。これを説明するための完全に機能するコマンドラインアプリケーションと、競合状態に関連する問題を次に示します。
#import <Foundation/Foundation.h>
typedef void(^MyTestBlock)(void);
@interface Foo:NSObject
- (id)initWithBlock:(MyTestBlock)aBlock;
- (void)someMethod;
@end
@implementation Foo {
MyTestBlock _block;
}
- (id)initWithBlock:(MyTestBlock)aBlock {
self = [super init];
if( !self ) { return nil; }
_block = aBlock;
return self;
}
- (void)someMethod {
dispatch_queue_t backgroundQueue = dispatch_queue_create("backgroundqueue", NULL);
dispatch_async(backgroundQueue, ^{
dispatch_queue_t innerQueue = dispatch_get_main_queue();
dispatch_async(innerQueue, ^{
if( _block){
NSLog(@"Will call block.");
_block();
}
});
});
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
__block NSObject *myObject;
Foo *myFoo = [[Foo alloc] initWithBlock:^{
myObject = [[NSObject alloc] init];
}];
[myFoo someMethod];
// this log statement should show that myObject is nil because it will (probably)
// be executed before your block.
NSLog((myObject)?@"Your object was created":@"Why is my object nil?");
// wait a little bit to resolve race condition (just for illustrative purposes)
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.4f * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog((myObject)?@"Your object was created":@"Why is my object nil?");
});
}
// this isn't a Cocoa app, so must call dispatch_main() at end of main
dispatch_main();
}