0

AFNetworkingを使用し、操作キュー (NSOperationQueue に似ています) を使用して、Clear Read APIへの一連の要求をキューに入れています。

私は基本的に URL の配列を持っており、それぞれに基づいて個別のリクエストを作成し、各リクエストをキューに入れ、リクエストをバッチで実行します。一度に 1 つずつ戻ってきて、タイムスタンプを付けてから、テーブル ビューのソースである Core Data に追加するので、テーブル ビューにデータが取り込まれます。

アイテムが正常に返されたときにのみ、タイムスタンプが発行されます。これは、アイテムが元の URL 配列の順序ではなく、いつ返されたかに基づいて並べ替えられることを意味します。そのため、返されるまでの時間が短い (API が処理するテキストが少ない) リクエストは、タイムスタンプが早く付けられ、テキストの量が多いため、後でタイムスタンプが付けられたアイテムよりも古いと見なされます。これは、正しい順序付けという点では明らかに当てはまりません。

最終的に、API 呼び出しの URL の配列が適切な順序になっているにもかかわらず、テーブル ビューは API がアイテムを返したタイミングに基づいて並べ替えられます。

これが私のコードです:

- (void)addArticlesFromURLs:(NSArray *)URLs fromSource:(NSString *)source {
    // Restrict amount of operations that can occur at once
    [[AFClearReadClient sharedClient].operationQueue setMaxConcurrentOperationCount:3];

    // Create an array to hold all of our requests to make
    NSMutableArray *requestOperations = [[NSMutableArray alloc] init];

    for (NSString *URL in URLs) {       
        // Create the request from the article's URL
        NSMutableURLRequest *request = [[AFClearReadClient sharedClient] requestWithMethod:@"GET" path:[NSString stringWithFormat:@"/v1/clear?url=%@&format=json", URL] parameters:nil];

        // Create the request operation and specify behaviour on success and failure
        AFHTTPRequestOperation *requestOperation = [[AFClearReadClient sharedClient] HTTPRequestOperationWithRequest:request
                                                                      success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                                            // Get the item NSDictionary from the JSON responseObject
                                                                            NSDictionary *item = [responseObject objectForKey:@"item"];

                                                                            // Get the values needed to create an article
                                                                            NSString *title = [item objectForKey:@"title"];
                                                                            NSString *URL = [item objectForKey:@"link"];
                                                                            NSString *body = [item objectForKey:@"description"];

                                                                            // Replace HTML entities with their actual characters
                                                                            title = [title stringByReplacingOccurrencesOfString:@"&" withString:@"&"];

                                                                            // Remove all HTML and formatting from body so only plain-text remains
                                                                            body = [self removeHTMLAndFormatting:body];

                                                                                // Add it to CoreData if there's actual content (easiest way to tell is checking body)
                                                                            if (![body isEqualToString:@""]) {
                                                                                NSManagedObjectContext *context = self.managedObjectContext;
                                                                                ArticleInfo *articleInfo = [NSEntityDescription insertNewObjectForEntityForName:@"ArticleInfo" inManagedObjectContext:context];
                                                                                articleInfo.source = source;
                                                                                articleInfo.body = body;
                                                                                articleInfo.title = title;
                                                                                articleInfo.url = URL;
                                                                                articleInfo.timeStamp = [NSDate date];

                                                                                NSError *error;
                                                                                [context save:&error];
                                                                            }
                                                                      }
                                                                      failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                                            NSLog(@"Request operation error: %@", error);
                                                                      }];

        // Save the request operation in an NSArray so all can be enqueued later
        [requestOperations addObject:requestOperation];
    }

    // Enqueue the request operations
    [[AFClearReadClient sharedClient] enqueueBatchOfHTTPRequestOperations:requestOperations progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
        [self.tableView reloadData];
    } completionBlock:^(NSArray *operations) {
        [self.tableView reloadData];
    }];
}

私のテーブルビューが正しい(一番上に新しい)アイテムを持つように、これを変更するにはどうすればよいですか?

4

2 に答える 2

2

を使用しuserInfoます。

AFHTTPRequestOperationsubclasses AFURLConnectionOperation、および触れずに通過AFURLConnectionOperationする辞書を宣言します。userInfoその目的は、操作が完了したときに使用するために必要なデータを追加できるようにすることです。操作をキューに追加する前に、次のようにします。

[requestOperation setUserInfo:@{ @"timestamp" : [NSDate date] };

これを完了ブロックで次のように取得します

NSDate *timestamp = [operation userInfo][@"timestamp"];

タイムスタンプは、操作がキューに追加された順序を反映します。

于 2013-07-03T23:39:17.967 に答える
0

よくわからないけどAFNetworking...

リクエストを作成する前に (for ループで) タイムスタンプを取得できます。

NSDate* stamp = [NSDate date];
AFHTTPRequestOperation *requestOperation = ...

次に、操作成功ブロックで:

...
articleInfo.url = URL;
articleInfo.timeStamp = stamp;
...

ブロックはタイムスタンプを保持し、成功時に設定します

于 2013-07-04T04:32:38.217 に答える