json解析多个url,一个接一个顺序或在哪里写另一个函数调用JSONRequestOperationWithRequest

时间:2013-10-14 07:07:38

标签: iphone json web-services nsurlconnection afnetworking

我已经解析了json。 json存储在数组中的结果,其中包含视频ID列表。 现在我想解析另一个检索视频细节的json,这个json将在循环中videoIDArray.count次解析

这是代码:

- (void)viewDidLoad
{
    [super viewDidLoad];

    videoIDArray = [[NSMutableArray alloc] init];
    viewArray = [[NSMutableArray alloc] init];

    //======Json Parsing

    NSString *urlstring = [NSString stringWithFormat:@"https://myURL/youtubeList"];
    NSURL *url = [NSURL URLWithString:urlstring];

    NSURLRequest *Request = [NSURLRequest requestWithURL:url];
    conn = [[NSURLConnection alloc] initWithRequest:Request delegate:self];
    if (conn) {
        webdata = [[NSMutableData alloc] init];
    }
    //==========
}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    if (connection==conn) {
        [webdata setLength:0];
    }
    if (connection==conn2) {
        [webdata2 setLength:0];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if (connection==conn) {
        [webdata appendData:data];
    }
    if (connection==conn2) {
        [webdata2 appendData:data];
    }

}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //-------conn getting list of videoID
    if (connection == conn) {
        NSString *str = [[NSString alloc] initWithBytes:[webdata bytes] length:[webdata length] encoding:NSUTF8StringEncoding];

        NSDictionary *Result = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];

        [videoIDArray addObjectsFromArray:[[[Result valueForKey:@"items"] valueForKey:@"id"] valueForKey:@"videoId"]];
        NSLog(@"Video ID %@",videoIDArray);

        //======conn2 is for getting detail of video base on videoID object
        for (int i=0; i<videoIDArray.count; i++) {
            NSString *urlstring = [NSString stringWithFormat:@"https://mydetailURL/videos/%@?v=2&alt=json",[videoIDArray objectAtIndex:i]];
            NSURL *url = [NSURL URLWithString:urlstring];

            NSURLRequest *Request = [NSURLRequest requestWithURL:url];
            conn2 = [[NSURLConnection alloc] initWithRequest:Request delegate:self];
            if (conn2) {
                webdata2 = [[NSMutableData alloc] init];
            }
        }
        //==========
    }

    if (connection==conn2) {
        [MBProgressHUD hideHUDForView:self.view animated:YES];
        [youtubeTableView reloadData];

        NSString *str = [[NSString alloc] initWithBytes:[webdata bytes] length:[webdata length] encoding:NSUTF8StringEncoding];

        NSDictionary *Result = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
        NSLog(@"ResultConn2 %@",Result);
        [viewArray addObject:[[[Result valueForKey:@"entry"] valueForKey:@"yt$statistics"] valueForKey:@"viewCount"]];
        NSLog(@"View Array %@",viewArray);
    }
}

问题是:它没有像循环那样多次解析,只是为了调用和崩溃的最后一个connectionDidFinishLoading方法..

有人能告诉我怎么做吗?

还有其他办法吗?

修改

使用AFNetworking

我改变了我的代码:

 for (int i=0; i<videoArray.count; i++) {
      [self parseWithUrl:[videoArray objectAtIndex:i]];
   }
 -(void)parseWithUrl: (NSString *)urlstr
  {
     NSString *tstr=[urlstr stringByReplacingOccurrencesOfString:@"\"" withString:@""];
     NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://myURL/feeds/api/videos/%@?v=2&alt=json",tstr]];
     NSURLRequest *request = [NSURLRequest requestWithURL:url];
     AFJSONRequestOperation *operation =
     [AFJSONRequestOperation JSONRequestOperationWithRequest: request
                                                success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                          //instead of NSLog i want to return result
                                                    NSDictionary *result  = (NSDictionary *)JSON;
                                                    NSLog(@"VideoResult %@",result);



                                                } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                                    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather"
                                                                                                 message:[NSString stringWithFormat:@"%@",error]
                                                                                                delegate:nil
                                                                                       cancelButtonTitle:@"OK" otherButtonTitles:nil];
                                                    [av show];
                                                }];



    [operation start];

 }

我想写:

-(NSDictionary *)parseWithUrl: (NSString *)urlstr

有可能吗?

如果是,那么建议我应该在哪里返回结果?

如果我想在完成json之后调用另一个方法然后在哪里编写调用代码

这是我的代码:     [self getData:self.weather]; 我的方法被称为我不想要的次数。

 success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                                                    self.weather  = (NSDictionary *)JSON;
                                                    [self getData:self.weather];
 .....

 .....
  }

2 个答案:

答案 0 :(得分:2)

您的问题源于以下事实:每个NSURLConnection连接都是异步运行的,因此您同时运行多个请求,但您的例程使用单个webData2,因此您的请求绊倒了彼此。

如果您希望保持当前的设计,而不是在for循环中启动所有第二组请求,则应该只请求第一组请求。然后让第二类请求的connectionDidFinishLoading启动下一个请求。 (您可以通过跟踪一些指示您正在处理哪个请求的数字索引来管理这个“下一个”过程,每次递增它。)

但是你问一下接一个地顺序完成这些请求。是否有任何理由不能同时执行(更准确地说,在第一次请求完成时,然后同时发出单个视频的详细请求)。在那种情况下,甚至比前一段中概述的笨拙修复更好,更合理的解决方案是基于NSOperation的实现:

  • 为每个连接使用单独的对象,以便各个请求不会相互干扰;

  • 享有NSURLConnection的并发性,但将并发请求的数量限制为一些合理的数量......通过使用并发请求,您将获得显着的性能优势;以及

  • 如果用户在所有这些请求都在进行中并且您想取消网络请求时取消视图控制器,则可取消。

如果您已经熟悉编写基于NSURLConnectionDataDelegate的代码,那么将其包含在NSOperation中并不会更糟。 (请参阅并发编程指南中的Defining a Custom Operation Object)我们可以引导您完成相同的步骤,但坦率地说,更容易使用AFNetworking。他们为你做了复杂的事情。


在编辑问题时,您会问是否可以写:

- (NSDictionary *)parseWithUrl: (NSString *)urlstr

虽然技术上可行,但您永远不希望主队列上的方法同步等待网络请求。如果parseWithURL无法在AFNetworking调用的success块内执行所需操作(例如,您可能会启动[self.tableView reloadData]或您的UI所需的任何内容),那么{{1}在自己的完成处理程序中返回字典,例如:

parseWithURL

答案 1 :(得分:0)

最后,我在AFNetworking

的帮助下解析了同步多个json解析

json解析成功调用AFNetworking中的另一个方法:link

这是代码:

- (void)getResponse:(void (^)(id result, NSError *error))block {
   NSString *weatherUrl = [NSString stringWithFormat:@"%@weather.php?format=json", BaseURLString];
   NSURL *url = [NSURL URLWithString:weatherUrl];
   NSURLRequest *request = [NSURLRequest requestWithURL:url];

  // 2
  AFJSONRequestOperation *operation =
   [AFJSONRequestOperation JSONRequestOperationWithRequest:request
  // 3
  success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
    //Success
               block(JSON,nil); //call block here
  }
 // 4
 failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)    {
      UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error Retrieving     Weather"
                                                 message:[NSString stringWithFormat:@"%@",error]
                                                delegate:nil
                                       cancelButtonTitle:@"OK" otherButtonTitles:nil];
       [av show];
  }];

// 5

[operation start];

}

呼叫将是:

 [self getResponse:^(id result, NSError *error) {
     //use result here
 }];