2017-01-08 21 views
1

Я использую UIRefreshControl на моем столе, чтобы обновлять элементы. И в конце я показываю UIAlertController, чтобы информировать пользователя о завершении обновления и количестве обновленных элементов. Довольно просто, и он отлично работает для одного. Если я пытаюсь обновить несколько раз подряд, иногда элемент управления обновлением не отменяется даже после отклонения предупреждения. Мне нужно перевернуть стол, чтобы он исчез.UIAlertController иногда предотвращает скрытие UIRefreshControl

Это код я использую, все UI материал красиво сделано на главной теме:

if(refreshControl.refreshing) { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self refreshItems]; 

      dispatch_async(dispatch_get_main_queue(), ^{ 
       [refreshControl endRefreshing]; 
       [self.tableView reload]; 
       [self showUpdateInfo];      
      }); 
     }); 
    } 

Любая идея, что может привести к этому?

EDIT: Это, как я создаю контроль обновления в коде (в viewDidLoad):

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString: @"Checking for updates…"]; 
[refreshControl addTarget: self 
        action: @selector(refreshOutdatedItems) 
     forControlEvents: UIControlEventValueChanged]; 

self.refreshControl = refreshControl; 
+0

Вы о создании UIRefreshControl в коде или используя свойство TableViewController? – Yan

+0

См. Редактирование в моем вопросе. – Koen

+0

Я пытался воспроизвести проблему. Ваш код, похоже, работает должным образом. Кстати, у вас есть dispach_sync, который на самом деле рухнул на меня. Это специально или должно быть dispatch_async? – Yan

ответ

-1

Я считаю, что это действительно нужно делать с Tableview не прокрутка назад вверх до UIAlertController представлена. Я попытался установить задержку для метода showUpdateInfo и, похоже, сработал. Я думаю, когда пользователь только тянет, как только потребуется полсекунды, чтобы показать проверку UIAlertController, если это поможет. Вот мой код

- (void)refreshOutdatedItems 
{ 
    NSLog(@"refresh"); 

    if (self.refreshControl.refreshing) { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      for (double i = 0 ; i < 100000000; i++){ 

      }; 

      dispatch_async(dispatch_get_main_queue(), ^{ 

       [self.refreshControl endRefreshing]; 
       [self performSelector:@selector(showUpdateInfo) withObject:nil afterDelay:0.5]; 

      }); 
     }); 
    } 
} 

Позвольте мне знать, если помогает.

+0

Отлично! Он работает даже немного более гладким (на мой вкус) с более короткой задержкой (0,1 сек). – Koen

+0

Я положил его обратно на 0,5 секунды, через 0,1 секунды все еще происходит. – Koen

+0

Я думаю, зависит от того, насколько далеко позади таблицы вид, когда обновление данных завершено. Возможно, есть способ обнаружить, когда tableview завершает анимацию, но может быть немного сложнее. – Yan

4

Задержка в произвольное время не является очень чистым решением. Реализация задержки, подсчитывая удвоение до 10 миллионов, также является чем-то вроде взлома на мой взгляд.

То, что я в конечном итоге делает вместо похож на этого псевдо-Swift:

let alert = UIAlertController(...) 
present(alert, animated: true) { 
    refreshControl.endRefreshing() 
} 

Это задерживает вызов endRefreshing() до тех пор, пока предупреждение представлено.

Мой реальный код с помощью Swift 3 и PromiseKit выглядит примерно так:

@IBAction func onRefresh() { 
    Repository.getNewData().then { data in 
     self.data = data 
     self.tableView.reloadData() 
    }.recover { error in 
     // Return a promise to make sure endRefreshing isn't called until the alert is presented. 
     return self.presentErrorAlert(message: "Some user-friendly message") 
    }.always { 
     self.refreshControl?.endRefreshing() 
    } 
} 

private func presentErrorAlert(message: String) -> Promise<Void> { 
    return Promise<Void> { fulfill, _ in 
     let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert) 
     alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) 
     self.present(alert, animated: true) { 
      fulfill() 
     } 
    } 
} 
+0

Это должна быть принятая задержка ответа на произвольную сумму - это взлом. –

0

Просто сбросить содержимое смещения вида таблицы:

- (void)endRefreshControl { 
    [self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.bounds.size.height) animated:YES]; 
    [self.refreshControl endRefreshing]; 
} 

Когда завершается ваша задача, вызов [self endRefreshControl];
скорее чем [self.refreshControl endRefreshing];

0

Это похоже на ошибку в Xcode. Даже решение Йохана Левина иногда кажется зависающим в Xcode 9.2.

Это не совсем то, что вы ищете, но это обходное решение: не используйте UIAlertController. Просто поместите текст, который вы имели в UIAlertController в UIRefreshControl как так:

refreshControl?.attributedTitle = NSAttributedString(string: "Pull to reload all reminders", attributes: [NSAttributedStringKey.foregroundColor: UIColor(red: 255.0/255.0, green: 182.0/255.0, blue: 8.0/255.0, alpha: 1.0)])