0

ビュー コントローラーと、Twitter API へのネットワーク リクエストを実行する別のクラス (TwitterCrawler) の 2 つのクラスがあります。最初のネットワーク リクエストはビュー コントローラーが読み込まれたときに行われ、2 番目のネットワーク リクエストはユーザーがボタンを押したときに行われます。

最初のリクエストが完了する前にユーザーがボタンを押した場合、それが終了するのを待ってから2番目のリクエストを実行することを意味します。

作成したキューに最初のリクエストを入れたとしても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 に答える