這裏的問題是,你似乎永遠不會執行你實例化的塊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)[email protected]"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,但在我們的Foo
上調用someMethod
之前,我們不會執行它。
編輯:
你的問題的編輯指出,該塊未發送到主隊列異步分派塊的上下文中執行。如果這是一個命令行應用程序,那麼您必須在main
的末尾調用dispatch_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)[email protected]"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)[email protected]"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();
}
希望這個答案幫助 - http://stackoverflow.com/questions/8878358/obj-c-block-variables – Jirapong