1

ブロック内に作成した NSObject があります。以下のコードに従って:

__block NSObject *myObject;

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

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

Iの定義に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はコンソールに出力されます。重要なのは、ブロックはそれ自体では実行されないということです。上記のコードでは、ブロックをクラスのivarとして設定していますが、を呼び出すまで実行しませsomeMethodFoo

編集:

質問を編集すると、メインキューに送信された非同期ディスパッチブロックのコンテキストでブロックが実行されないことが示されます。これがコマンドラインアプリケーションの場合はdispatch_main()、の最後で呼び出す必要がありますmainmanのページを参照してください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 に答える