0

我正在使用AFNetworking并使用操作队列(类似于 NSOperationQueue)将一堆请求排队到Clear Read API

我基本上有一组 URL,我根据每个请求创建单独的请求,将每个请求排入队列,然后批量执行请求。它们一次一个地返回,然后我添加时间戳,然后将它们添加到 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];
    }];
}

我将如何改变这一点,以便我的 tableview 具有正确(最新在顶部)顺序的项目?

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 回答