在UITabBarController中切换选项卡后,UIRefreshControl卡住了

时间:2014-06-21 11:36:58

标签: ios iphone objective-c refresh uirefreshcontrol

我有一个UITableViewController作为UINavigationController中的根视图控制器,UINavigationController又是UITabBarController中的一个视图控制器。所有这些都挂在了Storyboard中。

我也在Storyboard中为我的表配置了UIRefreshControl,通常在拉动时看起来应该是这样:

Normal UIRefreshControl

但是,如果我在其他标签之间切换一次或两次,它看起来像这样:

Buggy UIRefreshControl

它没有旋转或任何东西,只是卡住了“满”,它一直保持这种状态,直到我完全拉动并触发刷新。

任何想法或建议都会欣赏。

18 个答案:

答案 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

开始刷新电话。

结果视频https://vid.me/LyuI

答案 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)

详细信息

  • Xcode版本10.3(10G8),Swift 5

问题

  • 在标签之间切换会冻结活动指示器
  • refreshControl.beginRefreshing(); refreshControl.endRefreshing()-将再发送一个请求/请求刷新事件

解决方案

refreshControl.removeTarget(actionTarget, action: selector, for: .valueChanged)
refreshControl.endRefreshing()
refreshControl.beginRefreshing()
refreshControl.addTarget(actionTarget, action: actionSelector, for: .valueChanged)

全部溶液和样品

How to use pull to refresh in Swift?

答案 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]viewWillAppearviewWillDisappear内完全正常工作。在某些情况下,您可能需要在两者中调用它。

希望这有帮助! :)

答案 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
    }
}