我有一个UITableViewController作为UINavigationController中的根视图控制器,UINavigationController又是UITabBarController中的一个视图控制器。所有这些都挂在了Storyboard中。
我也在Storyboard中为我的表配置了UIRefreshControl,通常在拉动时看起来应该是这样:
但是,如果我在其他标签之间切换一次或两次,它看起来像这样:
它没有旋转或任何东西,只是卡住了“满”,它一直保持这种状态,直到我完全拉动并触发刷新。
任何想法或建议都会欣赏。
答案 0 :(得分:12)
user2009606几乎是正确的,我通过调用
修复了它[refreshControl endRefreshing];
开启
viewWillAppear:
刷新标签后,refreshControl现在可以正常运行,与其状态无关。
答案 1 :(得分:11)
我知道这已经非常晚了,但是我觉得迟到总比没有好。
不幸的是,没有一个给定的答案对我有用。唯一有效的是viewWillAppear中的这段可怕的代码:
self.refreshControl = nil;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(refreshFunction) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
基本上每次视图出现时我都会重新创建UIRefreshControl。虽然在发出以下警告时它仍然有效:
尝试在空闲时更改刷新控件是 强烈劝阻,可能无法正常工作。
我真的很惊讶这仍然是一个问题(现在仍然在iOS 9中看到这一点)。希望这可能对其他人有所帮助。
答案 2 :(得分:5)
总结并提供完整的解决方案。
问题:
如果UIRefreshControl在屏幕转换期间动画,它将保持可见但不会动画。视频https://vid.me/Bkb7
此外,如果启动了刷新动画但未完成,然后执行了转换,则UIRefreshControl将被隐藏但仍然卡住。视频https://vid.me/Bkb7
解决方案:
在viewWillAppear上启动UIRefreshControl动画,并在viewDidDisappear上结束它。保存刷新过程的状态以了解何时显示UIRefreshControl。
Bellow是整个解决方案,它也可以处理正确的动画和简单的拉动以刷新动画。
添加到UITableView或子类
初始化:
/// Refresh indicator
var refreshControl = UIRefreshControl()
/// Refresh state
var isRefreshing = false
/// Refresh controll update funcion. Set to enable pull to refresh
var refreshControllUpdateFunction: (() -> ())?
/// Prepeares UIRefreshControll. Call from init
func initRefreshControl(){
addSubview(refreshControl)
refreshControl.addTarget(self, action: "refreshControllTarget", forControlEvents: .ValueChanged)
refreshControl.beginRefreshing()
isRefreshing = true
}
Superview事件处理程序:
/// Call on viewWillApper
func superviewWillApper(){
if isRefreshing && !refreshControl.refreshing{
startRefreshAnimation()
}
}
/// Call on viewDidDisapper
func superviewDidDisappear(){
endRefreshAnimation(false, dataFetched: !isRefreshing)
}
UIRefreshControl动画处理程序:
/// Presents animating UIRefreshControll
func startRefreshAnimation(){
refreshControl.beginRefreshing()
contentOffset = CGPointMake(0, -refreshControl.bounds.size.height)
isRefreshing = true
}
/// Hides UIRefreshControll and saves state of refresh
func endRefreshAnimation(wasEmpty: Bool, dataFetched: Bool){
refreshControl.endRefreshing()
isRefreshing = !dataFetched
if !wasEmpty{
setContentOffset(CGPointZero, animated: true)
}else{
setContentOffset(CGPointZero, animated: false)
}
}
添加
table.isRefreshing = true
开始刷新电话。
答案 3 :(得分:4)
以下解决方案可能会对您有所帮助。
CGFloat yTableViewOffset;
- (void)viewDidLoad {
yTableViewOffset = kNilOptions;
}
- (void)viewWillAppear:(BOOL)animated
{
if(yTableViewOffset != kNilOptions) {
CGPoint offset = CGPointMake(tableView.contentOffset.x, yTableViewOffset);
[refreshControl beginRefreshing];
tableView.contentOffset = offset;
}
}
- (void)viewWillDisappear:(BOOL)animated
{
if(refreshControl.isRefreshing) {
yTableViewOffset = tableView.contentOffset.y;
[refreshControl endRefreshing];
}
}
答案 4 :(得分:4)
只需在endRefreshing
中调用viewWillDisappear:
即可解决所有问题。
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.refreshControl endRefreshing];
}
在viewWillAppear:
中执行相同的操作会导致刷新控件在拉桌子时发生奇怪的旋转。
答案 5 :(得分:2)
我刚看到同样的事情。我最终做的是对viewWillDisappear进行endRefreshing,至少可以解决这个问题。 但是,回到选项卡我希望它重新开始旋转,因为我重新启动刷新过程并再次调用beginRefreshing,但事实并非如此。它是在我向下钻取导航然后回来的情况下。
答案 6 :(得分:1)
在刷新控件旋转时,如果您提供其他一些控制器并在“结束刷新”之前返回;刷新动画将被卡住。
以上所有答案对我都没有用,我不想设置bool并在视图控制器的整个生命周期中遵循它。
我的解决方案是将以下代码添加到viewWillAppear的末尾。
在Objc中;
if (self.refreshControl.isRefreshing) {
[self.refreshControl endRefreshing];
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated: true];
[self.refreshControl beginRefreshing];
}
在Swift中;
if self.refreshControl.isRefreshing {
self.refreshControl.endRefreshing
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y-self.refreshControl.frame.size.height), animated: true)
self.refreshControl.beginRefreshing;
}
逻辑是;每当捕捉到刷新控制处于动画状态时,它将在不知道其是否卡住的情况下将其停止,然后重新运行动画。
希望有帮助。
答案 7 :(得分:1)
Swift中最好的解决方法:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//fixes bug with refreshControl freezing while switching tabs
if tableView.contentOffset.y < 0 {
tableView.contentOffset = .zero
}
}
答案 8 :(得分:0)
只需添加以下代码,它就可以在所有条件下完美运行。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard refreshControl.isRefreshing else { return }
refreshControl.endRefreshing()
refreshControl.beginRefreshing()
tableView?.contentOffset = CGPoint(x: 0, y: -(refreshControl.bounds.height))
}
答案 9 :(得分:0)
refreshControl.beginRefreshing(); refreshControl.endRefreshing()
-将再发送一个请求/请求刷新事件refreshControl.removeTarget(actionTarget, action: selector, for: .valueChanged)
refreshControl.endRefreshing()
refreshControl.beginRefreshing()
refreshControl.addTarget(actionTarget, action: actionSelector, for: .valueChanged)
答案 10 :(得分:0)
您可以尝试
refreshControl.beginRefreshing()
refreshControl.endRefreshing()
在viewWillAppear中,这应该可以工作。
答案 11 :(得分:0)
通过将以下代码放在viewWillDisappear中,我能够解决此问题
DispatchQueue.main.async {
self.refreshControl.beginRefreshing()
self.refreshControl.endRefreshing()
}
如果将以上代码放置在viewWillAppear中,则微调器将在几秒钟内进行动画处理并关闭,在两种情况下,该问题都将得到解决,但是,从用户的角度来看,微调器不可见,因此最好将其放置在viewWillDisappear中。
答案 12 :(得分:0)
此question中的答案解决了我的问题
基本上在viewWillAppear
上再次停止和启动微调器答案 13 :(得分:0)
我无法在导航发生之前调用endRefreshing工作,所以我从另一端接近问题并在viewWillAppear上检查tableView contentOffset是否为负数使tableView恢复为0。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.tableView.contentOffset.y < 0)
{
[self.tableView setContentOffset:CGPointZero animated:YES];
}
}
答案 14 :(得分:0)
希望我最终可以帮助解决这个问题:
使用带有Pull-To-Refresh控件的UITableView时出现问题。 通过添加UITableViewController,可以轻松解决这个问题。
UITableViewController *tableController = [[UITableViewController alloc] init];
tableController.automaticallyAdjustsScrollViewInsets = NO;
[tableController willMoveToParentViewController:self];
[self addChildViewController:tableController];
tableController.tableView = self.containerTableView;
tableController.refreshControl = self.refreshControl;
这样你只需将UITableView包装在一个控制器中,[self.refreshControl endRefreshing]
在viewWillAppear
或viewWillDisappear
内完全正常工作。在某些情况下,您可能需要在两者中调用它。
希望这有帮助! :)
答案 15 :(得分:0)
我想要点阿尔伯特解决方案而不是他的风格。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_table.contentOffset = CGPointMake(_table.contentOffset.x, _table.contentOffset.y + 1.0f);
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
_table.contentOffset = CGPointMake(_table.contentOffset.x, _table.contentOffset.y - 1.0f);
}
答案 16 :(得分:0)
我有一个collectionView,我确实设置了它的contentInset。
推送一些ViewControllers,然后按home键,然后返回并弹出,UIRefreshControl始终位于顶部。
最后我暂时使用此代码避免它。 (丑陋但停止它始终显示在顶部)
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.refreshControl endRefreshing];
CGPoint currentContentOffset = self.collectionView.contentOffset;
[self.collectionView setContentOffset:CGPointMake(currentContentOffset.x,
currentContentOffset.y - 1.0f)
animated:YES];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGPoint currentContentOffset = self.collectionView.contentOffset;
[self.collectionView setContentOffset:CGPointMake(currentContentOffset.x,
currentContentOffset.y + 1.0f)
animated:YES];
}
答案 17 :(得分:-1)
在多次遇到同样的问题之后,我决定为它创建一个库cmake
。
如前所述,refreshControl
需要停留在viewDidDisappear(_:)
上并从viewWillAppear(_:)
开始。
以编程方式启动refreshControl
动画时,tableView.contentOffset
需要设置为适当的值。
tableView.setContentOffset(CGPoint(x: 0, y: -(refreshControl?.bounds.height ?? 60) - topOffset), animated: true)
var topOffset: CGFloat {
if let navigationBar = navigationController?.navigationBar, navigationBar.isTranslucent == true {
return navigationBar.bounds.height + UIApplication.shared.statusBarFrame.height
} else {
return 0
}
}