0

正しく返されるJSONの結果をテーブルビューに入れようとしています。問題は、結果をインスタンス変数に割り当てても、情報が返されるブロック内のデータにしかアクセスできないことです。私のコードは次のとおりです。

NSURL *url = [NSURL URLWithString:@"http://www.my_url.com.br/app/?type=list&info=15,16&lat=some_data&long=some_data"];

ASIHTTPRequest *_request = [ASIHTTPRequest requestWithURL:url];
ASIHTTPRequest *request = _request;

request.requestMethod = @"POST";
[request addRequestHeader:@"Content-Type" value:@"application/json"];

[request setDelegate:self];
[request setCompletionBlock:^{
    NSString *responseString = [request responseString];

    NSLog(@"Response: %@", responseString);
    NSDictionary *root = [NSJSONSerialization JSONObjectWithData:request.responseData options:0 error:nil];
    self.data = [root objectForKey:@"listing"];

    NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

}];
[request setFailedBlock:^{
    NSError *error = [request error];
    NSLog(@"Error: %@", error.localizedDescription);
}];

[request startAsynchronous];

NSLog(@"Data only: %@", data);  //At this point, the "data" content is nil

これは私の「ListDataController.h」ファイル定義です:

@interface ListDataController : UITableViewController{
ApplicationCell *tmpCell;
    NSArray *data;
    UILabel *status ;       
UINib *cellNib;
}

@property (nonatomic, retain) IBOutlet ApplicationCell *tmpCell;
@property (nonatomic, retain) NSArray *data;

返されたJSON:Data self:({Icon = "Baseball.png"; Name = Baseball; NumRatings = 106; Price = "$ 2.98"; Publisher = "Super Sportz、Inc."; Rating = "3.5";}、{ Icon = "Checkers.png"; Name = Checkers; NumRatings = 87; Price = Free; Publisher = "Gameitoids、Inc."; Rating = 4;})

問題は、jsonの結果を割り当てても、ブロック外のインスタンス変数「data」にアクセスできないのはなぜですか?

4

4 に答える 4

1

dataブロック外にアクセスできますが、に設定されていnilます。data思った瞬間ではなく、おそらく適切に設定されています。

最終ログを実行する時点では、完了ブロックはまだ実行されていません。リクエストは非同期です。つまり、完了ブロックは将来のある時点で実行されます。これは、ブロックを操作するときに理解するための重要な概念です。

更新

取得したデータを処理するには、完了ブロックから目的のデータを呼び出すことができます。

[request setCompletionBlock:^{
    NSString *responseString = [request responseString];

    NSLog(@"Response: %@", responseString);
    NSDictionary *root = [NSJSONSerialization JSONObjectWithData:request.responseData options:0 error:nil];
    self.data = [root objectForKey:@"listing"];

NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

    [self handleData:self.data];  // you would have to define this method your self

}];

に基づいてUIを更新する場合は、メインスレッドでself.data実行することを確認する必要があります。handleData

いくつかのリンク:

于 2013-03-13T14:58:35.913 に答える
0

ここで何が起こるかはあなたのログです

NSLog(@"Data only: %@", data);  //At this point, the "data" content is nil

データを取得する前に十分に実行されます。ブロックを使用して非同期リクエストを使用しています。つまり、実行はメインスレッドの実行に影響を与えることなく別のスレッドで行われます。

個別のスレッドが完了すると、完了ブロックが実行されます。したがって、応答はこの時点でのみデータにロードされます。

理解しやすくするために

  • ログブロックと完了ブロックの両方にブレークポイントを設定します

完了ブロックの前にログの実行が行われていることがわかります

編集:応答が割り当てられた後、完了ブロックで操作を実行できますdata

   [request setCompletionBlock:^{
        NSString *responseString = [request responseString];

        NSLog(@"Response: %@", responseString);
        NSDictionary *root = [NSJSONSerialization JSONObjectWithData:request.responseData options:0 error:nil];
        self.data = [root objectForKey:@"listing"];

        NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly


        //DO here WHATEVER you want to do after getting response
    //eg:
        [table reloadData]


    }];

すべてのデータを取得するときのリクエストは完了ブロックを実行します。したがって、応答を取得した後に実行したいことはすべて、完了ブロックで実行できます。

于 2013-03-13T14:53:49.593 に答える
0
  1. タイミング(上記の2つの答えのように)
  2. ブロックの外側にある変数に書き込むには、変数宣言の前に__blockディレクティブを使用する必要があります。インスタンス変数がこれに特別であるかどうかはわかりませんが、最終的にivarに割り当てる前に、結果を格納するために一時変数を使用できることを確認してください。
于 2013-03-13T15:05:42.683 に答える
0
NSLog(@"Data returned: %@", data);  //Everything works well. The data returned is printed correctly

罰金。あなたの問題は何ですか?これが完了ブロックです。すべてのデータを受信したときに実行されます。その時点より前のデータへのアクセスは、最良の場合はnilになり、最悪の場合は古い/間違った/予測できないデータになります。

于 2013-03-13T15:08:36.900 に答える