0

私はjsonを解析しました。ビデオIDのリストを含む配列に格納されたjsonの結果。ここで、ビデオの詳細を取得する別の 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);
    }
}

問題は次のとおりです。ループ内の回数だけ解析していません。最後に 1 回の connectionDidFinishLoading メソッドが呼び出されてクラッシュしました。

誰かがこれを行う方法を教えてもらえますか?

これを行う他の方法はありますか?

編集

AFネットワーキングを使用

私は自分のコードを次のように変更しました:

 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の を使用しているため、リクエストは互いにつまずきます。

for2 番目の一連の要求をすべて開始するループを作成するのではなく、現在の設計を維持したい場合は、最初の要求のみを要求する必要があります。次にconnectionDidFinishLoading、2 番目のタイプのリクエストに対して、次のタイプのリクエストを開始します。(この「次の」プロセスは、処理中のリクエストを示す数値インデックスを追跡し、毎回インクリメントすることで管理できます。)

しかし、これらのリクエストを順番に、次々と行う方法を尋ねます。それらを同時に実行できない理由はありますか (より正確には、最初の要求が完了したときに、個々のビデオの詳細要求を同時に発行します)。そのシナリオでは、前の段落で概説した不器用な修正よりも優れた、より論理的な解決策は、次のようなNSOperationベースの実装です。

  • 個々のリクエストが互いに干渉しないように、接続ごとに個別のオブジェクトを使用します。

  • の同時実行性NSURLConnectionを享受しますが、同時リクエストの数を妥当な数に制限します...同時リクエストを使用すると、パフォーマンスが大幅に向上します。と

  • これらのリクエストがすべて進行中で、ネットワーク リクエストをキャンセルしたい場合に、ユーザーがビュー コントローラを閉じた場合にキャンセルできます。

NSURLConnectionDataDelegateベースのコードの記述に既に慣れている場合は、それを でラップすることNSOperationはそれほど悪くありません。( Concurrency Programming GuideDefining a Custom Operation Objectを参照してください。) そのための手順を順を追って説明しますが、率直に言って、 AFNetworkingを使用する方がはるかに簡単です。彼らはあなたのために複雑なことをしました。


質問の編集で、次のように書くことができるかどうか尋ねます。

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

技術的には可能ですが、メイン キューのメソッドがネットワーク リクエストを同期的に待機することは望ましくありません。parseWithURLAFNetworking 呼び出しのブロック内で必要なことを実行できない場合success(たとえば[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 で別のメソッドが呼び出されます:リンク

コードは次のとおりです。

- (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 に答える