1

我有一个在块内创建的 NSObject。根据下面的代码:

__block NSObject *myObject;

[self myMethod:^{
    myObject = [[NSObject alloc] init];
    ....
}];

if(myObject == nil){
    NSLog(@"Why is my object nil?!");
}

myMethod我的定义中有以下内容:

  backgroundQueue = dispatch_queue_create("backgroundqueue", NULL);

            dispatch_async(backgroundQueue, 
                           ^{

                               dispatch_async(dispatch_get_main_queue(), 
                                              ^{
                                                  if(block){
                                                      block();//Never called.
                                                  }
                                              });

然而,该块永远不会被调用。

4

2 回答 2

3

这里的问题是您似乎从未执行过您在其中实例化的块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到控制台。关键是块不会自己执行。someMethod在上面的代码中,虽然我们将块设置为类的 ivar,但在调用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();
}
于 2012-11-26T11:02:37.417 回答
0

您忘记在myMethod. 试试下面的代码。

typedef void(^MyBlock)();

- (void)myMethod:(MyBlock)aBlock
{
    aBlock();
}
于 2012-11-26T11:11:41.313 回答