【问题标题】:Show activity indicator animation when button pressed按下按钮时显示活动指示器动画
【发布时间】:2011-09-05 08:46:39
【问题描述】:

我有一个名为“同步”的按钮。当点击/按下时,它将数据发送到网络服务器并由服务器检索答案(需要一段时间并冻结 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

【问题讨论】:

  • 我还喜欢在所有内容前面放置一个黑色背景、0.5 alpha UIView 以使它们变暗并禁用任何用户与 UI 元素的交互。
  • 输入被禁用,所以你不需要这个,也不需要这个,你的意思是
  • 似乎主要问题是整个程序冻结,直到它从服务器得到答案。所以按下按钮 - 应用程序冻结 - 答案到了。

标签: ios nsurlconnection activity-indicator


【解决方案1】:

在 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

【讨论】:

  • 使用未声明的标识符“waitAlert”?
  • 在您的代码中声明 UIAleartView *waitAlert 您只是没有我正在使用的变量。所以在代码中声明它们。
  • 成功了,tahnks,但冻结的问题没有解决 =(
  • 您是否尝试从正在上传数据的线程显示此警报?然后需要时间。显示来自主线程或来自单独方法的警报并从 performSelector 中调用该方法。
  • 试过 i9t 但不知道如何让它正常工作。现在它像以前一样在冻结后显示微调器
【解决方案2】:

您的同步请求阻塞了 UI 线程,这就是活动指示器无法启动的原因。您应该出于多种原因异步使用 NSURLConnection,这就是其中之一。

代替:

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];
}

【讨论】:

  • 预期; token before : token on: - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
  • 我希望您没有将这些方法粘贴到其他方法中?现在给我看看你的代码。请编辑您的问题并将其放在那里,它不会在评论中很漂亮。
  • 我把它贴在每个方法之外
  • 你粘贴的东西有误。如果您需要帮助,请编辑您的问题并插入您目前拥有的代码,否则我无法帮助您。
  • 我粘贴了你的代码块,但它没有工作,所以我怎么能粘贴错误的东西?我现在得到未声明的标识符 returnData 我是否必须添加更多代码才能解决此错误?然后让returnData实例变量=>我必须自己写一些代码吗?
【解决方案3】:

对于同步使用:(错误的形式,但有效的解决方案)

//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];
}

【讨论】:

  • 当我将它放入 IBAction 时,还使用了未声明的标识符 myDoRequest
【解决方案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) 
...

// When request is done
[indicatorView stopAnimating];
[indicatorView release];

【讨论】:

  • 看来我不必在某处创建视图或将其添加到标题中...?当我添加你的代码时,它和以前一样吗?
  • @Martin 你必须将它添加到你当前的视图中,addSubView:
  • 我添加了setFrameaddSubview 以便您了解全貌
  • 似乎主要问题是整个程序冻结,直到它从服务器得到答案。所以按下按钮 - 应用程序冻结 - 答案到了。
  • 我猜你正在通过同步调用调用服务器,那么你必须在 UI 刷新的最后一个周期 之前UIActivityIndicatorView 添加到你的控制器视图中。 (例如在viewDidLoad 或通过您的NIB file)。然后在发出请求之前按下按钮时只需调用[indicatorView startAnimating];
【解决方案5】:

创建:

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];

最终完成后,从视图中移除微调器并释放。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-24
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 2011-10-13
    相关资源
    最近更新 更多