UIRefreshControl - beginRefreshing not working when UITableViewController is inside UINavigationController

后端 未结 15 768
梦如初夏
梦如初夏 2020-11-28 03:03

I\'ve setup a UIRefreshControl in my UITableViewController (which is inside a UINavigationController) and it works as expected (i.e. pull down fires the correct event). Howe

相关标签:
15条回答
  • 2020-11-28 03:44

    None of the other answers worked for me. They would cause the spinner to show and spin, but the refresh action itself would never happen. This works:

    id target = self;
    SEL selector = @selector(example);
    // Assuming at some point prior to triggering the refresh, you call the following line:
    [self.refreshControl addTarget:target action:selector forControlEvents:UIControlEventValueChanged];
    
    // This line makes the spinner start spinning
    [self.refreshControl beginRefreshing];
    // This line makes the spinner visible by pushing the table view/collection view down
    [self.tableView setContentOffset:CGPointMake(0, -1.0f * self.refreshControl.frame.size.height) animated:YES];
    // This line is what actually triggers the refresh action/selector
    [self.refreshControl sendActionsForControlEvents:UIControlEventValueChanged];
    

    Note, this example uses a table view, but it could just as well have been a collection view.

    0 讨论(0)
  • 2020-11-28 03:44

    If you use Rxswift for swift 3.1, can use below:

    func manualRefresh() {
        if let refreshControl = self.tableView.refreshControl {
            self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.height), animated: true)
            self.tableView.refreshControl?.beginRefreshing()
            self.tableView.refreshControl?.sendActions(for: .valueChanged)
        }
    }
    

    This work for swift 3.1, iOS 10.

    0 讨论(0)
  • 2020-11-28 03:46

    It seems that if you start refreshing programmatically, you have to scroll the table view yourself, say, by changing contentoffset

    [self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
    

    I would guess the reason for this is that it could be undesirable to scroll to the refresh control when user is in the middle/bottom of the table view?

    Swift 2.2 version by @muhasturk

    self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
    

    In a nutshell, to keep this portable add this extension

    UIRefreshControl+ProgramaticallyBeginRefresh.swift

    extension UIRefreshControl {
        func programaticallyBeginRefreshing(in tableView: UITableView) {
            beginRefreshing()
            let offsetPoint = CGPoint.init(x: 0, y: -frame.size.height)
            tableView.setContentOffset(offsetPoint, animated: true)        
        }
    }
    
    0 讨论(0)
  • 2020-11-28 03:47

    Fort Swift 2.2+

        self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
    
    0 讨论(0)
  • 2020-11-28 03:50

    The already mentioned approach:

    [self.refreshControl beginRefreshing];
     [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
    

    would make the spinner visible. But it wouldn't animate. The one thing I changed is the order of these two methods and everything worked:

    [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
    [self.refreshControl beginRefreshing];
    
    0 讨论(0)
  • 2020-11-28 03:50

    In addition to @Dymitry Shevchenko solution.

    I found nice workaround to this issue. You can create extension to UIRefreshControl that overwrites method:

    // Adds code forgotten by Apple, that changes content offset of parent scroll view (table view).
    - (void)beginRefreshing
    {
        [super beginRefreshing];
    
        if ([self.superview isKindOfClass:[UIScrollView class]]) {
            UIScrollView *view = (UIScrollView *)self.superview;
            [view setContentOffset:CGPointMake(0, view.contentOffset.y - self.frame.size.height) animated:YES];
        }
    }
    

    You can use new class by setting custom class in Identity Inspector for refresh control in Interface Builder.

    0 讨论(0)
提交回复
热议问题