方法内部的阻止不会返回

时间:2014-06-04 08:37:12

标签: ios objective-c facebook

我必须采用以下方法。

我希望此方法在用户喜欢该页面时返回1,如果用户不喜欢则返回0。但是在该函数之前似乎调用了该​​块。

有没有办法解决这个问题?

谢谢!。

-(NSInteger) userWithId:(NSString *)fb_id likesPageWithID:(NSString *)page_id {

    __block NSInteger returnValue;
    NSString *fbGraphPath = [NSString stringWithFormat:@"/%@/likes/%@",fb_id,page_id];
    NSLog(@"%@",fbGraphPath);
    [FBRequestConnection startWithGraphPath:fbGraphPath parameters:nil HTTPMethod:@"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
        NSLog(@"%@",result);
        if(error) {
            NSLog(@"%@",error);
        } else {
            if([result count] == 0) {
                NSLog(@"%@",[result objectForKey:@"data"]);
                returnValue = 0;

            } else {
                    NSLog(@"%@",[result objectForKey:@"data"]);

                returnValue = 1;

                }
            }
    }];
    return returnValue;
}

3 个答案:

答案 0 :(得分:3)

我可以想到三种方法:

通知中心

如Apurv的回答所示,您可以使用通知中心广播结果:

- (void)userWithId:(NSString *)fb_id likesPageWithID:(NSString *)page_id {

    __block NSInteger returnValue;
    NSString *fbGraphPath = [NSString stringWithFormat:@"/%@/likes/%@",fb_id,page_id];
    NSLog(@"%@",fbGraphPath);
    [FBRequestConnection startWithGraphPath:fbGraphPath parameters:nil HTTPMethod:@"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
        NSLog(@"%@",result);
        if(error) {
            NSLog(@"%@",error);
        } else {
            if([result count] == 0) {
                NSLog(@"%@",[result objectForKey:@"data"]);
                returnValue = 0;

            } else {
                    NSLog(@"%@",[result objectForKey:@"data"]);

                returnValue = 1;

                }
            }
        [[NSNotificationCenter defaultCenter] postNotificationName:@"mynotif" object:nil userInfo:@{@"result":@(returnValue)}];
    }];
}

就个人而言,除非我需要播放价值,否则我不会这样做。使用通知会增加一些不必要的开销。

<强>条件

这是最简单的实现,它不会改变你使用这种方法的人,但是有点矫枉过正。

- (NSInteger)userWithId:(NSString *)fb_id likesPageWithID:(NSString *)page_id {

    __block NSInteger returnValue;
    NSCondition *condition = [NSCondition new];
    [condition lock];
    NSString *fbGraphPath = [NSString stringWithFormat:@"/%@/likes/%@",fb_id,page_id];
    NSLog(@"%@",fbGraphPath);
    [FBRequestConnection startWithGraphPath:fbGraphPath parameters:nil HTTPMethod:@"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
        NSLog(@"%@",result);
        if(error) {
            NSLog(@"%@",error);
        } else {
            if([result count] == 0) {
                NSLog(@"%@",[result objectForKey:@"data"]);
                returnValue = 0;

            } else {
                    NSLog(@"%@",[result objectForKey:@"data"]);

                returnValue = 1;

                }
            }
        [condition lock];
        [condition signal];
        [condition unlock];
    }];
    [condition wait];
    [condition unlock];
}

此外,此代码将阻止正在运行的线程。因此,调用此方法的线程不能与运行FB的完成处理程序的线程相同。

<强>块

在我看来,这是最好的。

- (void)userWithId:(NSString *)fb_id likesPageWithID:(NSString *)page_id withCompletionHandler:(void (^)(NSInteger))handler {

    __block NSInteger returnValue;
    NSString *fbGraphPath = [NSString stringWithFormat:@"/%@/likes/%@",fb_id,page_id];
    NSLog(@"%@",fbGraphPath);
    [FBRequestConnection startWithGraphPath:fbGraphPath parameters:nil HTTPMethod:@"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
        NSLog(@"%@",result);
        if(error) {
            NSLog(@"%@",error);
        } else {
            if([result count] == 0) {
                NSLog(@"%@",[result objectForKey:@"data"]);
                returnValue = 0;

            } else {
                    NSLog(@"%@",[result objectForKey:@"data"]);

                returnValue = 1;

                }
            }
        handler(returnValue);
    }];
}

很容易使用它:

[var userWithId:fb_id likesPageWithID:page_id withCompletionHandler:^(NSInteger result) {
    // use result for whatever you need
}];

希望它有所帮助。

答案 1 :(得分:1)

阻止异步工作。因此,当您调用startWithGraphPath时,执行将直接转到下一行。调用方法完成执行后,将调用完成块。所以,一般来说你不应该返回值。但是在块结束时,您应该使用封装在其中的适当值来广播通知。

答案 2 :(得分:1)

@Apurv给出的答案几乎总是正确的,您可以执行以下任一操作:

  • 传入一个块,其中包含您要检索的数据的参数(最适合一对一)
  • 触发通知(最适合发布订阅)。

虽然直接回答你的问题,但如果你有一个提供异步回调的外部库,并且 真的 喜欢同步调用它,你可以执行以下操作: / p>

选项1:使用信号量

信号量停止执行,直到发出信号继续。

-(NSInteger) userWithId:(NSString *)fb_id likesPageWithID:(NSString *)page_id {

    dispatch_semaphore_t querySemaphore = dispatch_semaphore_create(0);

    __block NSInteger returnValue;        
    [FBRequestConnection startWithGraphPath:fbGraphPath parameters:nil HTTPMethod:@"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {

        returnValue = xyz; //calculate your return value
        dispatch_semaphore_signal(querySemaphore);


    }];
    dispatch_semaphore_wait(querySemaphore, DISPATCH_TIME_FOREVER);
    return returnValue;
}

选项2:使用Runloop(hacky)

如果您的块正在调用完成调度的同一线程/队列,则会发生死锁。避免这种情况的一种方法是使用运行循环。

for (int i = 0; i < 5; i++) //time-out
{
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    if (returnValue)
    {
        return returnValue;
    }
}
return nil;