UIAlertController有时会阻止UIRefreshControl隐藏

问题描述:

我在桌面上使用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];      
      }); 
     }); 
    } 

任何想法可能是什么原因?

编辑:这是我在代码中创建刷新控制(在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

我相信它真的有与没有的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

延迟任意时间不是一个很干净的解决方案。在我看来,通过计算两倍到一千万的数字来实现延迟也是一种破坏。

我最终什么事做,而不是与此类似伪斯威夫特:

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

它延缓调用endRefreshing(),直到提出警告。

我用斯威夫特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

这应该是公认的答案 - 以任意数量推迟是一种破解。 –

只需重置内容表视图的偏移:

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

当任务完成后,调用[self endRefreshControl];
而比[self.refreshControl endRefreshing];

这似乎是Xcode中的一个bug。即使Johan Levin的解决方案有时似乎在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)])