【问题标题】:XCode: Stop Animating Activity Indicator after Executing a Method From Another FileXCode:从另一个文件执行方法后停止动画活动指示器
【发布时间】:2013-06-14 07:45:36
【问题描述】:

好的,这看起来应该很简单 - 我要做的就是从我的 SignIn.m (ViewController) 调用我的 ServerConnect.m (NSObject)、NSURL 连接请求方法并在 NSURL 请求之后停止 UIActivityIndi​​catorView已完成。当然,如果我在主线程上做这一切:

- (IBAction)forgotPassword:(id)sender {    
    [activityIndicator startAnimating];
    connection = [[ServerConnect alloc] init];
    [connection sendUserPassword:email withSecurity:securityID];
    [activityIndicator stopAnimating];
}

然后,一切都将并发执行,并且活动指示器将在连接方法完成之前启动和停止......

因此,我尝试将连接请求放在辅助线程上:

- (IBAction)forgotPassword:(id)sender {
    [NSThread detachNewThreadSelector: @selector(requestNewPassword:) toTarget:self withObject:userEmail.text];
}

- (void) requestNewPassword:(NSString *)email
{
    [self->thinkingIndicator performSelectorOnMainThread:@selector(startAnimating) withObject:nil waitUntilDone:NO];

    //Make NSURL Connection to server on secondary thread
    NSString *securityID = [[NSString alloc] init];
    securityID = @"security";
    connection = [[ServerConnect alloc] init];
    [connection sendUserPassword:email withSecurity:securityID];

    [self->thinkingIndicator performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:NO];
}

但是,我在这里也看不到活动指示器,这可能是由于 NSURL 请求在辅助线程上无法正常运行(即,由于某种原因,它没有像在请求时那样收集 xml 字符串主线程)。

构建我的代码以使其工作的正确方法是什么?我很惊讶在尝试弄清楚如何让我的活动指示器在另一个文件中的方法完成执行后简单地停止时涉及了多少工作。有没有办法串联(一个接一个)而不是同时运行代码?任何帮助将不胜感激。

更新为显示:sendUserPassword:(NSString *)withSecurity:(NSString *)

- (void)sendUserPassword:(NSString *)emailString
            withSecurity:(NSString *)passCode;
{
    NSLog(@"Making request for user's password");
    newUser = NO;
    fbUser = NO;
    forgotPassword = YES;
    NSString *post = [NSString stringWithFormat: @"email=%@&s=%@", emailString, passCode];
    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
    //Construct the web service URL
    NSURL *url = [NSURL URLWithString:@"http://www.someurl.php"];
    //Create a request object with that URL
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                           cachePolicy:NSURLRequestReloadIgnoringCacheData
                                                       timeoutInterval:90];
    [request setURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];
    //Clear out the existing connection if there is one
    if(connectionInProgress) {
        [connectionInProgress cancel];
    }
    //Instantiate the object to hold all incoming data
    xmlData = [[NSMutableData alloc] init];

    //Create and initiate the conection - non-blocking
    connectionInProgress = [[NSURLConnection alloc] initWithRequest: request
                                                           delegate:self
                                                   startImmediately:YES];
}

【问题讨论】:

  • 你能展示一下sendUserPassword:withSecurity:方法的实现吗?
  • 您是否尝试过使用 gcd 而不是直接管理线程?甚至是在完成块中停止动画的异步连接?
  • 我没有,@Abizern,你能提供一个例子或参考来说明如何做到这一点吗?
  • 好吧,既然你正在发送一个异步请求,为什么不在适当的委托方法中收到预期的响应后停止指示器?
  • 提示: 通知。 或者您可以做我们其他人所做的事情 - 使用像 AFNetworking 这样的库,它会为您处理所有这些,并抽象出您需要做的大量工作来支持异步网络和块。

标签: ios xcode ios6 nsthread uiactivityindicatorview


【解决方案1】:

一个建议尝试如下:

- (IBAction)forgotPassword:(id)sender
{
    [self->thinkingIndicator startAnimating];
    [NSThread detachNewThreadSelector: @selector(requestNewPassword:) toTarget:self withObject:userEmail.text];
}

- (void) requestNewPassword:(NSString *)email
{
    //Make NSURL Connection to server on secondary thread
    NSString *securityID = [[NSString alloc] init];
    securityID = @"security";
    connection = [[ServerConnect alloc] init];
    [connection sendUserPassword:email withSecurity:securityID];

    [self->thinkingIndicator performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:NO];
}

【讨论】:

  • 不幸的是,同样的结果... :\ 任何其他想法,@Midhun?
【解决方案2】:

我最终合并了 NSNotification 系统 (see Multithreading for iOS) 来解决我的问题。不赞成这样做的任何原因:

“将更新从代码的一部分发送到另一部分的一种简单方法是 Apple 的内置 NSNotification 系统。

这很简单。你得到 NSNotificationCenter 单例(通过 [NSNotificationCenter defaultCenter])并且:

1.) 如果您有想要发送的更新,请调用 postNotificationName。你只需给它一个你自己编的唯一字符串(比如“com.razeware.imagegrabber.imageupdated”)和一个对象(比如刚刚下载完图片的ImageInfo)。

2.) 如果您想了解此更新何时发生,请调用 addObserver:selector:name:object。在我们的例子中,ImageListViewController 将想知道何时发生这种情况,以便它可以重新加载适当的表格视图单元格。放置它的好地方是 viewDidLoad。

3.) 不要忘记在视图卸载时调用 removeObserver:name:object。否则,通知系统可能会尝试在未加载的视图(或更糟的是未分配的对象)上调用方法,这将是一件坏事!”

【讨论】:

    【解决方案3】:

    你可以试试这个,它在完成时使用一个块。我有类似的事情right here

    // Turn indicator on
    
    // Setup the request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
    [request setTimeoutInterval: 90.0];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];
    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
    
    [NSURLConnection sendAsynchronousRequest:request
                  queue:[NSOperationQueue currentQueue]
                  completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                  // Its has finished but sort out the result (test for data and HTTP 200 i.e. not 404)
                  NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                  if (data != nil && error == nil && [httpResponse statusCode] == 200)
                  {
    
                     // Connection finished a gooden
                     // Do whatever you like with data
                     // Stop indicator
    
                  }
                  else
                  {
                     // There was an error, alert the user
                     // Do whatever you like with data
                     // Stop indicator
    
                  }
    
              }];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多