0

我已经解析了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];
 .....

 .....
  }
4

2 回答 2

2

您的问题源于这些NSURLConnection连接中的每一个都是异步运行的,因此您同时运行了许多请求,但是您的例程使用的是单个webData2,因此您的请求相互之间存在问题。

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

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

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

  • 享受 的并发NSURLConnection,但将并发请求的数量限制在某个合理的数量……通过使用并发请求,您将获得显着的性能优势;和

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

如果您已经熟悉基于编写NSURLConnectionDataDelegate的代码,那么将其包装在 anNSOperation中并不会更糟。(请参阅并发编程指南中的定义自定义操作对象。)我们可以引导您完成执行此操作的步骤,但坦率地说,使用AFNetworking要容易得多。他们已经为您完成了复杂的工作。


在您对问题的编辑中,您询问是否可以写:

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

虽然在技术上是可行的,但您永远不希望主队列上的方法同步等待网络请求。如果parseWithURL不能success在 AFNetworking 调用的块内做它需要做的事情(例如,你可能会启动一个[self.tableView reloadData]或任何你的 UI 需要的东西),那么parseWithURL在它自己的完成处理程序中返回字典,例如:

- (void)parseWithURL: (NSString *)urlstr completion:(void (^)(NSDictionary *))completion
{
    ...

    AFJSONRequestOperation *operation =
    [AFJSONRequestOperation JSONRequestOperationWithRequest: request
                                                    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

                                                        completion(JSON); // call the completion block here

                                                    } failure:...];
}
于 2013-10-14T08:24:28.657 回答
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
 }];
于 2013-10-14T12:58:04.510 回答