0

バックグラウンドで実行する必要があるタスクを実行したい。このタスクには、Web サービスの応答の解析が含まれます。時間がかかるので、これをバックグラウンドで実行したかったのです。以下は、バックグラウンドタスクを実行しようとしたコードです。

//**When a button is tapped this method will be called.**
dispatch_queue_t myQueue=dispatch_queue_create("My Queue",  NULL);

    dispatch_async(myQueue, ^{

        [self getDataPetioleGraph];//**This will parse the webservice response and the output will be stored in a array for populating on tableview**


        dispatch_async(dispatch_get_main_queue(), ^{


            [tableViewObj reloadData];
        });

    });

-(void)getDataPetioleGraph{

NSString *soapContent=[NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                       "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
                       "<soap:Body>"
                       "<GetDataPetioleGraph xmlns=\"http://tempuri.org/\">"
                       "<Account_Number>%@</Account_Number>"
                       "</GetDataPetioleGraph>"
                       "</soap:Body>"
                       "</soap:Envelope>",@"38003"];
NSMutableURLRequest *request=[[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:@"web service link is here"]] autorelease];
NSString *contentLength=[NSString stringWithFormat:@"%d",[soapContent length]];
[request addValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"http://tempuri.org/GetDataPetioleGraph" forHTTPHeaderField:@"SOAPAction"];
[request addValue:contentLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[soapContent dataUsingEncoding:NSUTF8StringEncoding]];    
getDPGConnection=[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
[getDPGConnection start];

しかし、上記の関数を呼び出すボタンをタップしても何も起こりません。私は他の答えを試しましたが、それでも解決策が得られません。誰が私がどこで間違ったのか教えてもらえますか。前もって感謝します。

4

6 に答える 6

0

デリゲート (実装した場合) が呼び出されない理由は、 queue によって関連付けられている未指定のバックグラウンド スレッドで接続を開始するためmyQueueです。この未指定のスレッドには実行ループがありません。実際のスレッドは、そのキューにディスパッチされるブロックごとに変わることさえあります。

ANSURLConnectionは にスケジュールする必要があります

a) 実行ループを持つ専用スレッド。または

b) a NSOperationQueue.

接続オブジェクトがスケジュールされる場所を明示的に指定しない限り、接続のデリゲート メソッドは、メソッドが接続に送信されたのと同じスレッドで実行されます。startこのスレッドに実行ループがない場合、デリゲートは呼び出されません。

ケース a) は次のように実装できます。

実行ループで NSURLConnection をスケジュールする

まず、専用スレッドで実行していることを確認し、このスレッドに実行ループがあることを確認します。これは、実行ループを追加するために注意を払ったメインスレッドまたはその他のスレッドにすることができます。(後者は必要以上にトリッキーなので、簡潔にするためにここでは説明しません)。

NSURLConnectionオブジェクトを作成し、すぐに開始されないようにします。

connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];

次に、現在のスレッド/実行ループで接続をスケジュールして開始します。

[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[self.connection start];

注意: この方法では、現在のスレッドの実行ループがデリゲートのスケジュールに使用されます。現在のスレッド以外のスレッドを指定する可能性はありません!

NSOperationQueue次に、デリゲートが実行される場所を使用します。

NSOperationQueue で NSURLConnection をスケジュールする

これは実際にはもっと簡単です。NSOperationQueue インスタンスが必要なだけで、次のように接続を開始します。

まず、NSOperationQueueデリゲートがスケジュールされるインスタンスを作成します。

self.queue = ...;  

NSURLConnectionオブジェクトを作成し、すぐに開始されないようにします。

connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];

接続をスケジュールして開始します。

[self.connection setDelegateQueue:self.queue];
[self.connection start];

上記はあなたの問題の一部を解決します。デリゲートを実装する方法、応答データを保存する場所、長い解析操作を処理キューにディスパッチする方法については説明していません。

専用クラスSimpleGetHTTPRequestを使用して GET リクエストを実装する Gist のサンプルを次に示します。これは、POST リクエストを実装するのに役立つ場合があります。

于 2013-07-17T09:08:33.507 に答える
0

いくつかの方法があります。

NSOperationQueues は、データを受信したら UI 関数を呼び出すことができる完了ブロックを提供するため、私は NSOperationQueues を使用するのが好きです。

例:

NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
    [self getDataPetioleGraph];
}];

NSOperationQueue * opQueue = [[NSOperationQueue new] autorelease];
[op setQueuePriority:NSOperationQueuePriorityNormal];
[opQueue addOperation:op];
//Once we receive the neccesary data we populate the views with it in in the main thread
op.completionBlock = ^{
    dispatch_async(dispatch_get_main_queue(), ^{
       [tableViewObj reloadData];
    });
};
于 2013-07-17T07:41:22.403 に答える
0

これには、NSThread、NSOperation、および使用した方法など、多くの方法があります。簡単な例を次に示します。

dispatch_queue_t jsonParsingQueue = dispatch_queue_create("parsingQueue", NULL);

// execute a task on that queue asynchronously
dispatch_async(jsonParsingQueue, ^{
    [self doYourJsonParsingAndReadingTask];
    //As once this done and you need to call any code in main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.viewController updateThingsWithNewData];
    });
});

// release the dispatch queue if ARC not enable
dispatch_release(jsonParsingQueue);
于 2013-07-17T07:42:41.057 に答える