Search code examples
iosswiftuitableviewuirefreshcontrol

UIRefreshControl control spins forever after inserting new row


I have a UITableView, that on the delegate of the UIViewController that adds a new item, inserts the row. The row gets correctly inserted.

However, the UIRefreshControl on the UITableView will not go away when dragging the UITableView after that.

extension FeedViewController: AddPostDelegate {
    func didAddPost(_ userPost: UserPost) {
        self.postsWrapper?.posts.insert(PostWrapper(type: PostType.user(userPost)), at: 0)
        self.tableView.beginUpdates()
        self.tableView.insertRows(at: [
            IndexPath(row: 1, section: 0)
            ], with: .automatic)
        self.tableView.endUpdates()
        self.refresher.endRefreshing()//Does nothing
    }
}

In viewDidLoad:

refresher = UIRefreshControl()
tableView.addSubview(refresher)
refresher.addTarget(self, action: #selector(didDragScrollView), for: .valueChanged)
refresher.layer.zPosition = -1//otherwise in front of the header cell when refreshing (iOS 9.2)

If I do not go to another view first than come back before attempting to pull for refresh, it always hangs spinning forever.

EDIT: It looks like the UIRefreshControl is no longer calling the target function AFTER I add a post.

Any ideas on why this may be occurring? How to fix that?


Solution

  • Make sure that beginRefreshing() was not called before the user pulled to refresh. If refreshControl.isRefreshing is true then the selector does not get called upon "pull to refresh".

    A simple test:

    let refreshControl = UIRefreshControl()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        refreshControl.addTarget(self, action: #selector(ViewController.refreshData), for: .valueChanged)
        tableView.refreshControl = refreshControl
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        // sets refreshControl.isRefreshing to true
        // before the user initiates it
        refreshControl.beginRefreshing()
    }
    

    Then the user pulls to refresh. Because refreshControl.isRefreshing is true the selector will not get called. If you remove refreshControl.beginRefreshing()in viewDidAppear, the selector will get called:

    @objc func refreshData() {
        print("refresh initiated")
        refreshControl.endRefreshing()
    }