2016-07-22 8 views
0

Не могли бы вы помочь мне решить проблему обновления пользовательского интерфейса моей программы, показывая экземпляр UIAlertView? В этой ситуации:Обновить UI в обработчике UIAlertAction

  1. Я нажимаю на панель инструментов «hide-button» и открывается alertView;
  2. В обработчике UIAlertAction (кнопка ОК) У меня есть код, где я сделать несколько операций:
    • удалить панель инструментов «скрыть кнопку» нажатой и установить элемент кнопка с индикатором активности, а не;
    • изготовление индикатора прокатки;
    • ТОЛЬКО И ТОЛЬКО ПОСЛЕ ПРЕДЫДУЩИХ ШАГОВ следующая часть кода должна запускаться, и модель данных обновляется, и поскольку она подключена к tableView с помощью NSFetchedResultsControllerDelegate, данные таблицыView будут автоматически обновляться. Этот шаг может занять некоторое время, поэтому крайне необходимо удерживать его асинхронно, и пока он обрабатывается, индикатор активности должен скатиться;
    • после этого происходит снятие сбоев индикатора активности индикатора, элемент кнопки панели инструментов с ним удаляется и возвращается «скрытая кнопка» (снята на 1-м шаге). FINISH.

Проблема с обновлением пользовательского интерфейса, когда я обменивать «скрыть кнопку» и «активность кнопки».

private var hideDataBarButtonItem: UIBarButtonItem? 
private var indicatorBarButtonItem = UIBarButtonItem(customView: UIActivityIndicatorView(activityIndicatorStyle: .Gray)) 

override func viewDidLoad() { 
    super.viewDidLoad() 
    ... 
    hideDataBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Stop, target: self, action: #selector(hideAllLoginData)) 
    toolbarItems?.insert(hideDataBarButtonItem!, atIndex: 2) 
} 

Это действие для hideDataBarButtonItem:

@IBAction func hideAllLoginData(sender: AnyObject) { 
    let confirmAlert = UIAlertController(title: "Hide all data?", message: "", preferredStyle: .Alert) 

    confirmAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in 
     // remove the clear-button, set the indicator button instead and start indicator rolling 
     self.toolbarItems?.removeAtIndex(2) 
     self.toolbarItems?.insert(self.indicatorBarButtonItem, atIndex: 2) 
     (self.indicatorBarButtonItem.customView as! UIActivityIndicatorView).startAnimating() 
     print("button with indicator added") 

     sleep(5) // -> CHECK: this moment indicator should be visible and rolling! 

     dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)) { 
      for section in self.resources { 
       for resource in section { 
        if resource.defRecord != nil { 
         resource.defRecord = nil 
        } 
       } 
      } 
      print("data cleared") 

      dispatch_async(dispatch_get_main_queue()) { 
       // remove indicator and set the clear-button back 
       print("button with indicator removed") 
       (self.indicatorBarButtonItem.customView as! UIActivityIndicatorView).stopAnimating() 
       self.toolbarItems?.removeAtIndex(2) 
       self.toolbarItems?.insert(self.hideDataBarButtonItem!, atIndex: 2) 
      } 
     } 
    })) 
    confirmAlert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)) 

    self.presentViewController(confirmAlert, animated: true, completion: nil) 
} 

Результат выполнения:

button with indicator added 
// -> 5 sec of awaiting, but that's nothing in interface changed! 
data cleared 
button with indicator removed 

Если я не удалить кнопку индикатора, я могу видеть это в конце концов, но он должен появиться раньше. Что я делаю неправильно? Спасибо!

+0

попробуйте переместить свой сон из основной нити в фоновый поток. В настоящее время ваш сон блокирует основной поток, поэтому UIKit не может ничего на нем, и он не запускает анимацию в это время. –

+0

@PeterK, он работает. Я действительно мог наблюдать за качением в течение 5 секунд и делать какие-либо действия пользовательского интерфейса. В этот вечер я собираюсь проверить, как это работает на реальном устройстве со многими записями и без функции сна. Если это было так легко решить, вы действительно Wizard :) Я отвечу. –

+0

Итак, теоретически, если сон (5) находится в положении выше, я бы увидел индикатор активности в случае, если это была настоящая задержка? Но через 5 сек. спать? И будет ли возможно делать действия пользовательского интерфейса, в то время как методы NSFetchedResultsControllerDelegate будут обновлять строки в моей таблице? –

ответ

0

Проблема решена. Это потому, что NSFetchedResultsController обновил интерфейс не в основном потоке. Мне пришлось деактивировать его делегат, пока моя модель обновлялась. Затем в основном потоке я должен активировать его снова и обновить данные tableView. Решение здесь (смотрите в комментариях):

 dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)) { 
      // clear the delegate in order to not to allow UI update by fetchedResultsController 
      self.resourceModel.nullifyFetchedResultsControllerDelegate() 
      for section in self.resources { 
       for resource in section { 
        if resource.defRecord != nil { 
         resource.defRecord = nil 
        } 
       } 
      } 
      print("data cleared") 

      dispatch_async(dispatch_get_main_queue()) { 
       // set the delegate back and update the tableView 
       self.resourceModel.setFetchedResultsControllerDelegate(self) 
       self.reloadResources() 
       self.tableView.reloadData() 

       // remove indicator and set the clear-button back 
       print("button with indicator removed") 
       (self.indicatorBarButtonItem.customView as! UIActivityIndicatorView).stopAnimating() 
       self.toolbarItems?.removeAtIndex(2) 
       self.toolbarItems?.insert(self.hideDataBarButtonItem!, atIndex: 2) 
      } 
     } 

PeterK, спасибо за ваши советы!

+0

Вы также можете использовать dispatch_async (dispatch_get_main_queue()) {} в каждом обратном вызове делегата и обновлять пользовательский интерфейс для каждого изменения делегата, он должен быть более восприимчивым с точки зрения пользователя. –

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

  • Нет связанных вопросов^_^