0

我有两个类,一个视图控制器和另一个(TwitterCrawler)对 Twitter API 执行网络请求。我在视图控制器加载时发出第一个网络请求,在用户按下按钮时发出第二个网络请求。

我希望在第一个请求完成时执行第二个请求,这意味着如果用户在第一个请求完成之前按下按钮,它会等待它结束然后执行第二个请求。

即使我将第一个请求放在我创建的队列中,dispatch_sync我在用户按下按钮时调用的命令也会在队列清空之前调用。

这是我的代码:

//TwitterCrawler.m

-(void) getTwitterUsersInPosition: (Position*) position
{
dispatch_queue_async(twitterQueue, ^ {        
    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

    [accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error){
        if (granted) {

            NSArray *accounts = [accountStore accountsWithAccountType:accountType];

            if (accounts.count > 0)
            {
                ACAccount *twitterAccount = [accounts objectAtIndex:0];
                NSArray *keys = [NSArray arrayWithObjects:@"geocode", @"count", nil];
                NSArray *objects = [NSArray arrayWithObjects:@"37.781157,-122.398720,100mi", @"100", nil];
                NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects
                                                                       forKeys:keys];

                SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:[NSURL URLWithString:@"https://api.twitter.com/1.1/search/tweets.json"] parameters:dictionary];
                [twitterInfoRequest setAccount:twitterAccount];
                // Making the request

                [twitterInfoRequest performRequestWithHandler: ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
                    //dispatch_async(dispatch_get_main_queue(), ^{
                    dispatch_async(twitterQueue, ^{
                        ...adding object to nsmutablearray* twitterUsers
                    });
                }];
              }
            } 
            else {
            NSLog(@"No access granted");
            }
    }];
});
}

-(void) printUsers
{
// wait for queue to empty
dispatch_sync (twitterQueue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        for (NSString* str in twitterUsers)
        {
            NSLog(@"%@",str);
        }
    });
});
}



//ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    twitter_crawler=[[TwitterCrawler alloc] initTwitterCrawler];
    [twitter_crawler getTwitterUsersInPosition:position];
}

- (IBAction)pressButton:(id)sender {
    [twitter_crawler printUsers];
}

twitterUsers因此,如果用户在填充来自第一个请求的数据之前按下按钮,它将返回一个空数组。

编辑:

队列是串行的,我以这种方式创建它:

dispatch_queue_t twitterQueue = dispatch_queue_create("com.example.MyQueue", NULL);
4

1 回答 1

4

dispatch_sync保证在通过该 API 排队的块被执行之前它不会返回。不多也不少。

如果twitterQueue是一个并发队列,那么入队的块dispatch_sync可能会立即执行,而不管其他块在做什么。如果是串行队列,则该块将在已经入队的内容之后执行。但是,如果将新项目添加到队列中,它们将在同步调度之后运行。

当队列被清空时做某事的想法通常不是一个有用的方法(除非你很难管理队列并且最后执行的项目保证是该任务的最后一个项目,可能会触发一个新的多块任务和重新使用队列)。

您最好使用信号量或调度障碍或任何其他分组机制来严格控制您的并发性,包括何时更新主队列。

这是一个很好的起点文档。还有一些更高级的并发指南可用。

于 2013-06-16T02:09:31.980 回答