2

OK, here is the code.

NSObject* (^executableBlock)(void) = ^NSObject*() {
    __block NSObject *refObj = nil;

    [Utility performAction:^() {
         if (conditionA)
              refObj = fooA;
         else
              refObj = fooB;
    };

    return refObj;
};

NSObject *result = executableBlock();   // result is nil

After executing the executableBlock, the result is nil and performAction block didn't be executed immediately and returned my expected value.

I know performAction block is executed within another thread and using the shared nil pointer refObj. Refer to Working with Blocks.

Here is my through, if I use GCD to call the performAction block and wait for its finish, how to rewrite it? Thanks!

Itachi
  • 5,777
  • 2
  • 37
  • 69

3 Answers3

0

I would considering the following re-structure:

    __block NSObject * result;
    void (^executableBlock)(NSObject *) =  ^void (NSObject * obj)
    {
        [self performAnActionWithBlock:^(BOOL success)
        {
            if (success) {
                result = obj;
                NSLog(@"results: %@", result);
            }else{
               result = nil;
            }

        }];
    };
    executableBlock(@"Hello");


//where:
-(void)performAnActionWithBlock:(void(^)(BOOL))block{
    block(YES);
}

You should then be able to call result from elsewhere

Louis Tur
  • 1,303
  • 10
  • 16
  • I don't think so, this'll cause unexpected behavior. I think you just want to share an obj pointer among blocks/threads. If the performAnActionWithBlock is async and didn't be invoked in background thread before I used obj pointer in main thread, so the result may be null. – Itachi Jun 26 '15 at 07:20
  • The same with @user3087154 , I think. – Itachi Jun 26 '15 at 07:21
0
void (^executableBlock)(NSObject*) = ^(NSObject *arg) {

[Utility performAction:^(NSObject *arg) {
     if (conditionA)
          arg = fooA;
     else
          arg = fooB;
}];

};

__block NSObject *result = nil;

executableBlock(result); // result will be changed in block

zhubch
  • 194
  • 1
  • 1
  • 8
0

By using semaphore, you can wait until a block is done.
But completion-block may be suitable in your case, i think.

NSObject* (^executableBlock)(void) = ^NSObject*() {
    __block NSObject *refObj = nil;

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    [self performAction:^() {
        if (conditionA)
            refObj = fooA;
        else
            refObj = fooB;

        dispatch_semaphore_signal(semaphore);
    }];

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    return refObj;
};
bluedome
  • 2,449
  • 1
  • 22
  • 17
  • Thanks for your tips, I just found an answer after searching keywords **dispatch_semaphore_create**. Link: http://stackoverflow.com/a/4326754/1677041 – Itachi Jan 19 '15 at 06:03