2012-04-24 2 views
2
.h 
@property (strong) NSString *reply; 

私は次の方法があります:私はまだ構文を考え出したていないNSURL Connection sendAsynchronousRequestレスポンスを保存するには?

.m 
@synthesize reply; 

- (void)send 
{ 
[NSURLConnection sendAsynchronousRequest:[self request] 
       queue:[[NSOperationQueue alloc] init] 
       completionHandler: 
         ^(NSURLResponse *response, NSData *data, NSError *error)  
         { 
          if (error) 
          { 
           //NSLog(@"Error,%@", [error localizedDescription]); 
           [self setReply: [[NSString alloc] initWithString:[error localizedDescription]]]; 
          } 
          else 
          { 
           //NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]); 
           [self setReply: [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]]; 
          } 
         }]; 

} 

は今、私がブロック/ハンドラから値を返すようにしようとしたが、どうやらこれが不可能である(またはを)。

ローカル変数を設定して返信(データ)の値を取得しようとしましたが、エラーが発生しました。

エラーが生成されなかった唯一の方法は、クラスプロパティを使用することです。しかし、[自己回答]の価値を読み取ろうとすると、それはヌルです。決して決してないと私は思うのです。

私はsendAsync関数がスレッド化され、非同期であることを理解しています。なぜなら、sendSynchronousRequestを使用すると、私はいつも返事を受け取るのですが、[self reply]の値はnullです。

私は間違っていますが、どのようにしてcompletionHandler内から値を返すことができますか?

編集#1:私には間違ったことをしているようです。私はコードをトレースしていましたが、同期送信を使用すると、すべて正常に動作しました。非同期のものを使うと、sendAsynchronousRequestへの実際の呼び出しは決して実行されませんでした。スレッドが呼び出されていない、つまり空の値であると私は思っていました。

編集#2:

[NSURLConnection sendAsynchronousRequest:[self request] 
       queue:[NSOperationQueue alloc] init 
       completionHandler: 
         ^(NSURLResponse *response, NSData *data, NSError *error)  
         { 
          if (error) 
          { 
           //NSLog(@"Error,%@", [error localizedDescription]); 
           [self setReply: [[NSString alloc] initWithString:[error localizedDescription]]]; 
          } 
          else 
          { 
           //NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]); 
           [self setReply: [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]]; 
          } 
         }]; 

[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 2]]; 

しかし、私はそれがどのように動作するかを理解し、完全にわからない:私は次のように追加することで、これを回避する方法を発見しました。私は、RunLoopが非同期操作を2秒間実行するように指示していると想像しています(私は、日付間隔を低い値に設定すると、ライブサーバーでのテストのためにヌル応答を取得するためです)。私が理解していないことは、RunLoopに実行を指示すると、あたかも現在のスレッドが終了しなかったかのように、すべてを永久にブロックし続けることです。

+0

私はこの問題/質問を理解していません。なぜブロック補完関数から値を返すことができないのですか? setReply関数は何をしますか?コードを表示 – Lefteris

+0

データが有効かNullかを確認するためにブレークポイントを設定します。 あなたは正しい軌道に乗っていますが、これは有効なようですが、使用できる情報が得られていない可能性があります。 –

+0

ブロックはvoid戻り値の型として指定されているため、ブロック自体は値を返すことができませんが、なぜ値を返す必要がありますか?私はあなたのsetReply関数を単に推測しているだけで、単にインスタンス変数の設定者ですか?この場合、ブロックから何も返す必要はありません。なぜなら、レスポンスはsetReplyのときにキャプチャされるからです。ローカル変数を使用してデータの値を取得するときに生成されるエラーは何ですか?あなたは、データを見るためにブレークポイントを設定することができます。また、あなたが受け取っているレスポンスコードをチェックします。 – tronbabylove

答えて

2

ほぼ一ヶ月後、私は私の問題への解決策を見つけた:

NSURLConnection* _connection = [[NSURLConnection alloc] initWithRequest:[self request] delegate:self startImmediately:NO]; 
    self.port = [NSPort port];                          
    self.runloop = [NSRunLoop currentRunLoop];                      
    [self.runloop addPort:self.port forMode:NSDefaultRunLoopMode]; 
    [_connection scheduleInRunLoop:self.runloop forMode:NSDefaultRunLoopMode]; 
    [_connection start]; 
    while (self.finished != YES) { 
     [self.runloop runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]];                  
    } 
    [self.runloop removePort:[self port] forMode:NSDefaultRunLoopMode]; 
    [_connection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

これは私のためにトリックをしました。私はNSConnectionのデリゲートメソッド(didReceiveResponse、didReceiveData、didFailWithError、connectionDidFinishLoading)を適切に実装しなければならないことを覚えておいてください。 しかし、現在は非同期で動作しており、UIはフリーズしておらず、適切なエラー報告があります。 誰かが同じ問題で立ち往生してくれるのを助けてくれることを願っています。

+1

ダウン投票の場合は、少なくとも理由を述べる時間が必要です –

0

あなたはあなたの財産の返信

@property (strong) __block NSString *reply; 

このキーワードは、ブロックの中からあなたの財産を書き込み可能になるの宣言に__blockキーワードを使用してみてください。

:あなたたとえば

//this block is used to define a waiting condition 
typedef BOOL (^ CheckBlock)(); 

- (BOOL)waitUntilBlockTrue:(CheckBlock)theBlock orTimeout:(int)timeout { 
    NSDate *waitingStartPoint = [NSDate date]; 
    BOOL stillNeedToWait = YES; 
    while (stillNeedToWait && theBlock()) { 
     stillNeedToWait = ([waitingStartPoint timeIntervalSinceNow]*(-1.0)) < timeout; 
    } 
    return stillNeedToWait; 
} 

あなたがこのメソッドを呼び出します。応答は要求がタイムアウトを受信するまで、またはされるまで、メインスレッドがブロックする方法について

EDIT

提案

+0

それを試してみましたが、違いはありませんでした。私の推測では、メインスレッドは非同期送信操作が終了するよりも速く終了するということです。しかし、私にこのことを教えてくれてありがとう。 –

+1

この非同期呼び出しを使用していて、メインスレッドが応答を待つようにしたい場合は、メインスレッドをブロックする必要があります。私はSenTestCaseでテストを書いている間にこの問題を抱えていました。メインスレッドをブロックするために使用しているメソッドを確認してください。 – bas

+0

返信してコードを追加していただき、ありがとうございます。残念ながら、ブロック関数に間違った型のパラメータを渡すエラーが発生しているので、ビルドすることはできません(unsigned char BOOLから(BOOL)^()への無効なブロックポインタ変換)。さらに、私はこれと同じ方法でさまざまなアプローチを使用しているように思えます。メインのキューに非同期送信を追加して、runLoopに10秒間(私のタイムアウト)それを伝えました。それはあなたがやっていることではありませんが、あなたがしたことが値が返されたらブロックを止めることはできません。 –

2

このrunUntilDateを取り除き[NSOperationQueue mainQueue]を使用してみてください。 ng。

[NSURLConnection sendAsynchronousRequest:[self request] 
      queue:[NSOperationQueue mainQueue] 
      completionHandler: 
        ^(NSURLResponse *response, NSData *data, NSError *error)...  
+0

私はそれを試みましたが、違いはありませんでした。それは実際に私が最初に試した方法でした。 –

関連する問題