2

「同期」というボタンがあります。タップ/押されると、データがWebサーバーに送信され、サーバーによって回答が取得されます(しばらく時間がかかり、GUI /ボタンがフリーズします)ので、サーバーからのデータ/回答まで「お待ちください」とアクティビティインジケータを追加するにはどうすればよいですかが到着し、テキスト/インジケーターが削除され、サーバーからの回答に置き換えられますか?

このコードは私のアプリをフリーズします:

- (IBAction) syncButtonTapped
{

[syncButton setEnabled:NO];
//resultText.text= @"Bitte warten ...";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex: 0];
NSString *docFile = [docDir stringByAppendingPathComponent: @"deck.txt"];
NSString *post = [NSString stringWithContentsOfFile:docFile encoding:NSUTF8StringEncoding error:nil];


NSString *post2 = [post stringByReplacingOccurrencesOfString:@"\n" withString:@","];
NSString *post3 = [post2 stringByReplacingOccurrencesOfString:@"\r" withString:@""];
NSString *post4 = [NSString stringWithFormat:@"{\"results\":[%@]}",post3];
NSString *urlString = [NSString stringWithFormat:@"http://storecheck.cortona.de/fetchresults.php?results=%@",[post4 stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease]; 
[request setURL:[NSURL URLWithString:urlString]]; 
[request setHTTPMethod:@"GET"];
 NSString *data4 = @"";
[data4 writeToFile: docFile atomically: NO encoding: NSUTF8StringEncoding error:nil];
//send request & get response

NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
}

私はiOS 10.6.7を搭載したMac Miniで作業しています

4

5 に答える 5

5

UIAleartView にアクティビティ インジケーターを追加すると役立ちます。これをチェックアウト...

UIAlertView *waitAlert = [[[UIAlertView alloc] initWithTitle:@"Please Wait...." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] autorelease];

[waitAlert show];

UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

// Adjust the indicator so it is up a few pixels from the bottom of the alert
indicator.center = CGPointMake(waitAlert.bounds.size.width / 2, waitAlert.bounds.size.height - 50);
[indicator startAnimating];
[waitAlert addSubview:indicator];
[indicator release];

編集:おそらく、アプリケーションがブロックされている理由は、このメソッドです

sendSynchronousRequest:(NSURLRequest *)request

次にメソッドの説明です。

同期ロードは、クラスによって使用可能になった非同期ロード コードの上に構築されます。非同期読み込みシステムが、この読み込み要求専用に生成されたスレッドで URL 読み込みを実行している間、呼び出しスレッドはブロックされます。同期ロードを実行するために、呼び出しスレッドで特別なスレッド化や実行ループ構成は必要ありません。

アプリケーションをブロックしたくない場合は、他のスレッドからこれを呼び出します。以下もお読みください。

重要: この呼び出しが失敗するまでに数分かかる可能性があるため (特に iOS でセルラー ネットワークを使用している場合)、GUI アプリケーションのメイン スレッドからこの関数を呼び出さないでください。

NSURLConnection のクラスリファレンスを参照してください。上記のブロックは両方ともそこから取得されます。

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html

于 2011-09-05T08:52:14.843 に答える
4

同期リクエストが UI スレッドをブロックしているため、アクティビティ インジケーターが開始されません。複数の理由から NSURLConnection を非同期で使用する必要がありますが、これもその 1 つです。

それ以外の:

NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];

行う:

NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
[conn release];

次に、returnData インスタンス変数を作成し、NSURLConnectionDeletgate メソッドを実装します。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    returnData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [returnData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
    // do whatever you need with your string and stop activity indicator
    [returnData release];
}
于 2011-09-06T08:31:56.080 に答える
4

同期使用の場合: (悪い形式ですが、有効な解決策)

//Right before the request is made
UIActivityIndicatorView* indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[indicatorView setFrame:CGRectMake(0, 0, 16, 16)];
[indicatorView setHidesWhenStopped:YES];
[indicatorView startAnimating];
[self.view addSubview:indicatorView];
// Create your request (synchronously or asynchronously) 
[self performSelector:@selector(myDoRequest:) withObject:self afterDelay:0.1];
//this gives time for the runloop to complete at least one screen draw..
...

-(void)myDoRequest:(id)sender {
   // Create your request (synchronously or asynchronously) 
   ...
   // When request is done
   [indicatorView stopAnimating];
   [indicatorView release];
}
于 2011-09-06T08:37:17.530 に答える
1

作成:

spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[spinner setCenter:CGPointMake(kScreenWidth/2.0, kScreenHeight/2.0)]; // I do this because I'm in landscape mode
[self.view addSubview:spinner]; // spinner is not visible until started

始める:

[spinner startAnimating]; 

止まる:

 [spinner stopAnimating];

最終的に完了したら、ビューからスピナーを削除して放します。

于 2011-09-05T09:09:28.193 に答える
1
//Right before the request is made
UIActivityIndicatorView* indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[indicatorView setFrame:CGRectMake(0, 0, 16, 16)];
[indicatorView setHidesWhenStopped:YES];
[indicatorView startAnimating];
[self.view addSubview:indicatorView];
// Create your request (synchronously or asynchronously) 
...

// When request is done
[indicatorView stopAnimating];
[indicatorView release];
于 2011-09-05T08:51:43.897 に答える