0

我如何将这个方法变成一个块,直到'request startWithCompletionHandler'块完成它的请求和它自己的块中的代码?

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

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

添加信息:是的,我希望外部函数等到内部函数完成

谢谢。

4

3 回答 3

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];
}

请注意 - 您不想在主线程上执行此操作,否则您将锁定用户界面。您还必须确保请求不会等待您从中调用它的线程上发生任何事情,否则您将最终陷入死锁。

于 2013-04-05T08:13:42.593 回答
-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) {
    ....
   }];
});
于 2013-04-05T08:10:19.057 回答
-1

使用 facebook 之类的 API,您永远不会预先知道请求将花费多长时间(网络条件的变化/两端的负载/ ....),所以我不会使用任何线程锁定/等待它。

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

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

    }];
  }
于 2013-04-05T08:55:03.953 回答