0

NSJSONSerializationメインスレッドにないように、いくつかのコードをリファクタリングしようとしています。現在、アプリの動作が少し遅いです。

このコードを以下のものにリファクタリングしたいと思いますが、構文、特にエラー処理に問題があります。たとえば、既存のコード (requestData: メソッド) を取得して、

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});

テーブルはデータをロードしなくなります。

助けてくれてありがとう。

-(void)requestData {

    [HUD showUIBlockingIndicatorWithText:@"Fetching JSON"];

    NSError *requestError = nil;

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
                                                          URLWithString:kURL]];

    NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];

    NSError *jsonParsingError = nil;

    if (requestError)
    {
        NSLog(@"sync. request failed with error: %@", requestError);
    }
    else
    {
        // handle data
       publicData =  [NSJSONSerialization JSONObjectWithData:response
                                                                    options:0
                                                                      error:&jsonParsingError];
        publicDataArray = [publicData objectForKey:@"data"];

    }

    /*
     for(publicDataDict in publicDataArray) {
     NSLog(@"data output is %@",[publicDataDict objectForKey:@"title"]);

     }
     */
    [self.mainTableView reloadData];

    [HUD hideUIBlockingIndicator];
}

これが私が使用したいコードです。

-(void)viewDidAppear:(BOOL)animated
{

    [HUD showUIBlockingIndicatorWithText:@"Fetching Data"];

    //1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //code executed in the background
        //2
        NSData* ghData = [NSData dataWithContentsOfURL:
                            [NSURL URLWithString:kURL]
                            ];
        //3
        NSDictionary* json = nil;
        if (ghData) {
            json = [NSJSONSerialization
                    JSONObjectWithData:ghData
                    options:kNilOptions
                    error:nil];
        }

        //4
        dispatch_async(dispatch_get_main_queue(), ^{
            //code executed on the main queue
            //5


            [self.tableView reloadData];
            [HUD hideUIBlockingIndicator];
        });

    });
}
4

4 に答える 4

2

多くの人は、プロセスをバックグラウンドに送信すると、アプリケーションの遅延が自動的に解消されると想定していますが、これは間違った想定です。CPU を集中的に使用するタスクをバックグラウンドに送信すると、CPU もブロックされます。マルチスレッドが有利に機能するためには、それについて整然としている必要があります。

さて、あなたの問題について、最も簡単な解決策は、Appleがすでに提供しているものを使用することです.NSURLConnectionが最善の策です.[NSData dataWithContentsOfURL:]を決して使用しないでください. 問題は NSJSONSerialization ではなく、ネットワーク リクエストです。

実際には 2 つのオプションがあります。

1) NSRULConnection デリゲート メソッドを使用し、JSON シリアル化メソッドを – connectionDidFinishLoading: デリゲート メソッドに配置します。

2) NSURLConnection のブロック メソッドを使用する [NSURLConnection sendAsynchronousRequest: queue: completionHandler:] (私の好み)

-(void)viewDidAppear:(BOOL)animated
{
    [HUD showUIBlockingIndicatorWithText:@"Fetching Data"];

    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    if (!error) {
        NSError *jsonError = nil;
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];

        if (jsonError) {
            NSLog(@"Error parsing JSON");
            //Optionally display error message here
        }else{

            self.globalDictionary = jsonDict;

            [self.tableView reloadData];
            [HUD hideUIBlockingIndicator];
        }

    }else
    {
        NSLog(@"Error with request");

        [HUD hideUIBlockingIndicator];
        //Optionally display error message here
    }


}];

}

注: globalDictionary は、テーブルに入力する NSDictionary インスタンスです。

于 2013-07-03T11:06:26.080 に答える
0

コードをリファクタリングする場合は、関数を使用してください。別の関数で特定のタスクを実行することを目的としたロジック/コードを作成する必要があります。また、通常の場合、関数の LOC は 20 を超えてはなりません。

あなたの問題について言えば、あなたはそれを正しく述べているように見えますが、tableView のソースを定義しているのを見ていません。JSON を任意のコンテナ オブジェクト Viz 辞書または配列に変換したかどうかを確認してください。

    -(void)viewDidAppear:(BOOL)animated
{
    [HUD showUIBlockingIndicatorWithText:@"Fetching Data"];

    [self fetchData];
}

-(void)fetchData
{
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  // switch to a background thread and perform your expensive operation

  NSData* ghData = [NSData dataWithContentsOfURL:
                            [NSURL URLWithString:kURL]
                            ];

  NSDictionary* json = nil;

  if (ghData) 
  {
    json = [NSJSONSerialization
                    JSONObjectWithData:ghData
                    options:kNilOptions
                    error:nil];
   }

   dispatch_async(dispatch_get_main_queue(), ^{
   // switch back to the main thread to update your UI
  [self.tableView reloadData];
  [HUD hideUIBlockingIndicator];
    });

 });
}
于 2013-07-03T10:37:23.810 に答える
-3

新しいアーキテクチャARCのプロジェクトを変換するために最初にリファクタリングしてみてください。これを古い回答に投稿して、ここを見てください:

私の投稿

これがあなたの助けになるか、コードをリファクタリングするアイデアを与えることを願っています;)

于 2013-07-03T10:06:47.987 に答える