从网站订购多个异步JSON解析



简要介绍我正在做的事情:我有两个数组,它们都包含表视图50%的信息。为什么?因为其中一个数组从互联网上获取当前信息,而另一个数组保存了用户数据。我不知道如何以一种非混乱的方式从互联网上获取当前信息,因为我是objective-C的业余爱好者,更不用说在objective-C中建立网络了。无论如何,因此互联网阵列正在使用AFNetworking提取与保存的阵列(保存在核心数据中)中的对象相对应的信息。因此它是异步的,这是我想要的。现在问题来了,或者至少我能从这种情况中得到什么。

我正在做一个for循环,它有效地统计保存数组中的对象,并为每个对象传递唯一的ID,以便可以下载、解析互联网上的相应信息并将其添加到互联网数组中。然而,由于网络是异步的,因此循环有效地同时从互联网下载所有信息。因此,对象按照先下载的顺序写入互联网阵列。因此,savedArray[0]与internetArray[0]中的对象不对应。正如你所能想象的,这是一个相当大的缺陷,因为当我将值插入tableView时,没有什么真正匹配/有意义。

我真的在寻找一种方法来推迟信息的下载,直到之前的下载完成并添加到internetArray,我到底该怎么做?现在是代码。以下是我获得适当密钥的位置:

for ( int i = 0; i < [mySavedObjects count]; i++) {
MySavedObject* mySavedObject = [mySavedObjects objectAtIndex:i];
[self retrieveMissingInformation: myObject.Id];
[self.tableView reloadData];
}

这里是我实际获得信息的地方(为了空间起见,简化了):

- (void)retrieveMissingInformation:(NSString *) Id
{
// create URL here.
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(@"Success");
// Do some safety checks & parse the JSON, returning a searchResult.
[searchResults addObject:searchResult];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
// Do some error messages etc.
}];
[queue addOperation:operation]; //where queue is an ivar NSOperationQueue.
}

最后,在cellForRowAtIndexpath中,我同时使用以下两种:

MySavedObject *mySavedObject = [mySavedObjects objectAtIndex:indexPath.row];

&

SearchResult *searchResult = [searchResults objectAtIndex:indexPath.row];

获取单元格的值。

抱歉有这么大的文字墙。我真的不够好,无法有效地解释事情,经常在术语上结结巴巴,不得不编造自己的例子。如果能帮我点这顿饭,我将不胜感激。

问候,
迈克。

好同事,您偶然发现了一种常见的设计模式。

正如您所看到的,对于异步请求,执行几乎是同时发生的,所以当您将"队列"视为for循环时,不能保证顺序。

您需要考虑下载队列的方式是递归。

换句话说,而不是:

// your current method of queue-ing the submission of data
for(int i = 0; i < arrData.count; i++)
{
[self doAsyncDataSendForIndex:i];
}

你需要开始做这样的事情:

// perform the first submit for the first element in your array
[self doAsyncDataSendForIndex:dataIndex];

// a completion callback method
-(void)asyncFinishDownloading
{
[self parseResult:serverReturnedData];
}
-(void)parseResult:(id)serverData
{
// do all the processing of the data that you need here
...
// update index for next round
dataIndex++;
// -----------------------------------------------------------------
// now at the end of this method, perform a recursive call 
// of your async download method again 
// -----------------------------------------------------------------
[self doAsyncDataSendForIndex:dataIndex];
}

使用回调委托的下载排队方式,您告诉代码只有在处理完最后一次异步下载后才能下载下一个数据。

现在,您可以使用许多库来帮助您处理异步事务。我自己使用ASIHttpRequest和ASIFormData,你也可以使用更新的AFNetworking。

-(void)asyncSubmitData:(id)someData
{
NSURL *url = [NSURL urlWithString:@"http://www.yourserver.com/...."];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
// setup your POST request parameters
[request setPostValue:someData forKey:@"someKey"];
...
// setup the completion callback delegate action
[request setCompletionBlock:^{
// process your server returned data here
NSString *serverResponse = [request responseString]; // raw server response
...
// increment your index and call your download method again
dataIndex++;
[self asyncSubmitData:[myArray objectAtIndex:dataIndex]];
}];

// setup fail block in case the server fails
[request setFailedBlock:^{
NSLog(@"Server error: %@", [[request error] localizedDescription];
}];

// start the asynchronous request now
[request startAsynchronous];
}

希望能有所帮助。

我想我理解你的问题,听起来你使用了错误的数据结构来存储数据。

您有一个正在生成请求的数组,这些请求的结果存储在一个单独的、不相关的数组中。

当您使用objectId生成信息请求时,是否可以将结果存储在NSDictionary而不是数组中,并使用objectId作为该数组的键?

成功方法中有NSURLRequest,因此如果它是查询字符串上的参数,则应该能够通过NSURLquery从请求中检索objectId

推迟信息下载并有效地使所有网络请求串行(一次一个)是可行的,但这不是一个很好的解决方案,因为并行网络请求通常很方便-例如,一次允许四个请求可能比串行所有请求花费更少的时间。

一个更好的解决方案是在数据返回时正确处理它。要做到这一点,您需要以更结构化的方式处理返回的数据。与其只是将其附加到数组中,不如执行以下操作之一:

A将返回的数据放入字典中。字典可以从索引或适当的键映射到返回的数据。(提示:如果您想将int作为关键字放入字典中,请构造一个包含该int的NSNumber。)建议使用此选项而不是B。

B将返回的数据插入数组。为了使其有意义,在进行任何提取之前,您应该用占位符对象填充数组,这些占位符对象表示"这部分数据尚未提取"。一个可能的占位符对象选择是NSNull——它只是一个表示null/nil的对象。

因此,您可以在cellForIndexPath中返回正确的项:通过查询字典或数组。

这两个数据结构的想法只是脑海中最明显的想法,毫无疑问还有其他方法可以解决这个问题。

最新更新