如何嵌套块以便它们同时结束

时间:2013-04-05 08:01:03

标签: ios objective-c grand-central-dispatch

如何将此方法转换为一个块,直到'request startWithCompletionHandler'块完成它的请求并且代码在自己的块中完成后才能完成?

我需要按顺序调用一系列块,但它们都需要代码才能发送请求。试图找到一种干净的方法来完成任务。

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

ADDED INFO:是的,我希望外部函数等到内部函数完成

感谢。

3 个答案:

答案 0 :(得分: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 :(得分:-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) {
    ....
   }];
});

答案 2 :(得分:-1)

使用像facebook那样的API,你永远不会知道请求需要多长时间(网络条件/负载的变化/ ....)所以我不会使用任何线程锁定/等待它。 / p>

如果你传递给你的方法一个块(它可以封装其他块以及顺序执行):

+(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>);
       }

    }];
  }