2013-04-05 4 views
0

Как бы превратить этот метод в блок, который не будет завершен, пока блок запроса requestWithCompletionHandler не завершит свой запрос и код в своем собственном блоке?Как я могу блокировать блоки, чтобы они заканчивались одновременно

У меня есть серия блоков, которые мне нужно вызвать в порядке, но все они требуют кода для отправки своих запросов. Попытка найти чистый способ выполнить задачу.

+(void)???????? ^block() 
{ 
    FBRequest *request = [FBRequest requestForGraphPath:kFacebookQueryMeKey]; 
    [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
     .... 
    }]; 
} 

ADDED INFO: да, я хочу, чтобы внешняя функция ждать, пока внутренняя функция не будет завершена

Спасибо.

ответ

1

Это зависит от того, что вы имеете в виду. Учитывая ваш пример кода, кажется, что вы хотите, чтобы ваша функция вызывала блок, когда завершается вложенный блок. Так что вы хотели бы что-то вроде этого:

+ (void)doMyThingWithBlock:(void(^)(void))block 
{ 
    FBRequest *request = [FBRequest requestForGraphPath:kFacebookQueryMeKey]; 
    [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 

     // do whatever you want with the connection ... 

     if (block) block(); 

    }]; 
} 

С другой стороны, может быть, вы хотите, чтобы внешняя функция ждать вложенного блока для завершения перед возвращением. В этом случае это немного сложнее. Вы должны использовать блокировку ждать блок, чтобы закончить, как это:

#define kMyThingNotDone 0 
#define kMyThingDone 1 

+ (void)doMyThingAndWait 
{ 
    NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:kMyThingNotDone]; 

    FBRequest *request = [FBRequest requestForGraphPath:kFacebookQueryMeKey]; 
    [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 

     // do whatever you want with the connection ... 

     [lock lock]; 
     [lock unlockWithCondition:kMyThingDone]; 

    }]; 

    [lock lockWhenCondition:kMyThingDone]; 
    [lock unlock]; 
} 

Будьте осторожны - вы не хотите, чтобы сделать это в главном потоке, или вы будете запирать пользовательский интерфейс. Вы также должны быть уверены, что запрос не будет ждать, пока что-нибудь случится в потоке, на который вы это вызвали, иначе у вас будет тупик.

-1

Если ваше единственное требование состоит в том, чтобы запрос выполнялся в порядке, и FBRequest не делает этого для вас (я не знаком с API), один из вариантов заключается в том, чтобы обернуть эти вызовы в последовательную очередь.

dispatch_queue_t mySerialQueue = dispatch_queue_create("com.mycompany.serializedrequests", NULL); 
dispatch_async(mySerialQueue, ^{ 
    FBRequest *request = [FBRequest requestForGraphPath:kFacebookQueryMeKey]; 
    [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
    .... 
    }]; 
}); 
-1

С API, подобным facebook, вы никогда не знаете заранее, как долго будет выполняться запрос (изменения в сетевых условиях/загрузка на их концах/....), поэтому я не буду использовать нити, блокирующие/ожидающие с ним.

Если вы передаете ваш метод блок (который может инкапсулировать другие блоки, а также быть выполнена последовательно):

+(void) getFacebookDataWithCompletion:(void (^)(<some parameters))completion { 

    FBRequest *request = [FBRequest requestForGraphPath:kFacebookQueryMeKey]; 
    [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 

     if (!error) 
     { 
      //Do your thing with the facebook result (update user info, ....) 
     } 
     if (completion) 
     { 
      //Now that you have what you need from fb run your block(s) 
      completion(<params>); 
     } 

    }]; 
    } 
Смежные вопросы