2015-08-14 3 views
1

Я работаю над приложением в iOS, где мне нужно начать вращение UIActivityIndicatorView, загрузить изображение на сервер, и когда загрузка будет завершена, прекратите вращать индикатор активности.UIActivityIndicatorView не отображается для продолжительности async-задачи

Я сейчас использую XCode 7 Beta и тестирую приложение на iOS-симуляторе как iPhone 6 и iPhone 5. Моя проблема заключается в том, что индикатор активности не заканчивается сразу после загрузки файла, но несколько (~ 28 секунд). Где я должен поместить свои звонки, чтобы он закончился?

У меня есть функция @IBOutlet, прикрепленная к кнопке, которую я использую для запуска процесса, который содержит функцию startAnimating(), и которая вызывает метод dispatch_async, который содержит вызов uploadImage, который содержит сигнал, ожидание и stopAnimating().

Обратите внимание, что

let semaphore = dispatch_semaphore_create(0) 
let priority = DISPATCH_QUEUE_PRIORITY_HIGH 

определены в верхней части моего класса.

@IBAction func uploadButton(sender: AnyObject) { 

     self.activityIndicatorView.startAnimating() 
     dispatch_async(dispatch_get_global_queue(priority, 0)) { 

     self.uploadImage(self.myImageView.image!) 

     } // end dispatch_async 

    } // works with startAnimating() and stopAnimating() in async but not with uploadImage() in async 


    func uploadImage(image: UIImage) { 

     let request = self.createRequest(image) 

     let session : NSURLSession = NSURLSession.sharedSession() 

     let task : NSURLSessionTask = session.dataTaskWithRequest(request, completionHandler: { 
      (data, response, error) in 

      if error != nil { 
       print(error!.description) 
      } else { 
       let httpResponse: NSHTTPURLResponse = response as! NSHTTPURLResponse 

       if httpResponse.statusCode != 200 { 
        print(httpResponse.description) 
       } else { 

        print("Success! Status code == 200.") 
        dispatch_semaphore_signal(self.semaphore) 
        } 
      } 
     })! // end dataTaskWithResult 

     task.resume() 

     dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) 
     self.activityIndicatorView.stopAnimating() 
    } // end uploadImage 

Это всего лишь одна версия моего кода, я переместил несколько вещей несколькими различными способами. Я попытался это:

@IBAction func uploadButton(sender: AnyObject) { 

     self.activityIndicatorView.startAnimating() 
     dispatch_async(dispatch_get_global_queue(priority, 0)) { 

     self.uploadImage(self.myImageView.image!) 
     dispatch_semaphore_signal(self.semaphore) 
     } // end dispatch_async 
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) 
    self.activityIndicatorView.stopAnimating() 
    } 

И несколько, несколько других способов перемещения моего кода, чтобы попытаться получить индикатор активности для отображения на время загрузки образа, а затем сразу же бросить курить. В некоторых случаях счетчик не появляется вообще на время выполнения программы. Я прочитал this сообщение и this вопрос, и мигрировал мой dispatch_semaphore_wait и stopAnimating() для метода uploadImage(), чтобы обойти это, но не могу найти достаточную информацию в документации UIActivityIndicatorView об обновлении пользовательского интерфейса, чтобы узнать любой другой способ ее обновления, хотя я считаю, что это может быть основной проблемой.

Все, что мне нужно для запуска счетчика, прежде чем процесс загрузки начнется (dataTaskWithRequest) и закончится, как только он сработает или завершится с ошибкой. Что я делаю не так?

ответ

2

Вместо использования семафоров, вы могли бы просто послать непосредственно в основной поток в вашей асинхронной задачи,

func uploadImage(image: UIImage) { 
    let request = self.createRequest(image) 
    let session : NSURLSession = NSURLSession.sharedSession() 
    let task : NSURLSessionTask = session.dataTaskWithRequest(request, completionHandler: { 
     (data, response, error) in 

     if error != nil { 
      print(error!.description) 
     } else { 
      let httpResponse: NSHTTPURLResponse = response as! NSHTTPURLResponse 

      if httpResponse.statusCode != 200 { 
       print(httpResponse.description) 
      } else { 
       print("Success! Status code == 200.") 
      } 
     } 

     // dispatch to main thread to stop activity indicator 
     dispatch_async(disptach_get_main_queue()) { 
      self.activityIndicatorView.stopAnimating() 
     } 
    })! // end dataTaskWithResult 

    task.resume() 
} // end uploadImage 
+0

Это исправляет проблему, хотя я невероятно расстроен, почему именно семафоры не работают. Есть ли причина в моем коде? – Jthami05

+0

Я не знаю достаточно о семафорах, чтобы ответить на это. Имея ограниченные знания, ваш код выглядит правильно. Но иногда GCD просто облегчает жизнь. – keithbhunter

+1

Я ничего не думаю о том, что код семафора, который вы используете, вызывает вызов 'self.activityIndicatorView.stopAnimating', который должен выполняться в основном потоке. Правильный ответ - решение Кита об использовании 'dispatch_async (disptach_get_main_queue()' (проголосовало) –

Смежные вопросы