Yalantis/PullToRefresh

Table cells go under Navigation bar

levin-ilya opened this issue · 6 comments

See image:
image

Spent a lot of time trying to debug with to luck. The only think I found is that contentOffset is not the same as before.

Before:
<UITableView: 0x7fd7908bd600; frame = (0 0; 375 667); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fd79049e540>; layer = <CALayer: 0x7fd7904bb360>; contentOffset: {0, -64}; contentSize: {375, 82}>

After pull down to refresh:
<UITableView: 0x7fe5d9073600; frame = (0 0; 375 667); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fe5d85aa6e0>; layer = <CALayer: 0x7fe5d8586c20>; contentOffset: {0, -40}; contentSize: {375, 82}>

Hi @levin-ilya! Could you provide a test project?

the demo has the same bug. while pulling state scroll to bottom to push new data. the contentOffset is wrong

+1 same issue on split view controller.i set tableview frame again to fix that.it also triggers itself to refresh for the first running time but there is no such problem in your demo.Should i create new issue for that trigger problem.

class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate {
let refresher = PullToRefresh()
var detailViewController: DetailViewController? = nil

deinit {
    tableView.removePullToRefresh(tableView.bottomPullToRefresh!)
    tableView.removePullToRefresh(tableView.topPullToRefresh!)
}
override func viewDidLoad() {
    super.viewDidLoad()
    setupPullToRefresh()
    self.title = ""
    var masterStruct : MasterStruct = MasterStruct(title : "" , hasDate : 0)


    getGlobalServerIp()
    masterStruct.downloadMaster{( value) -> Void in
        if !value.isEmpty{
            globalMasterStructArray = value
            self.tableView.reloadData()
        }else{
            self.alert(message: "Veri Alınamadı.Sunucu Adresinizi Kontrol Edin.", title: "")
            globalMasterStructArray = value
            self.tableView.reloadData()
        }
    }
    if let split = self.splitViewController {
        let controllers = split.viewControllers
        self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
    }


}
func startRefreshing(){
    tableView.startRefreshing(at: .top)

}


override func viewWillAppear(_ animated: Bool) {
    self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed
    SwiftSpinner.show("Yükleniyor.")
    super.viewWillAppear(animated)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}



// MARK: - Segues

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetail" {
        if let indexPath = self.tableView.indexPathForSelectedRow {
            let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
            controller.selectedMaster = globalMasterStructArray[indexPath.row].title
            controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem
            controller.navigationItem.leftItemsSupplementBackButton = true

        }
    }
}

// MARK: - Table View

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return globalMasterStructArray.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    //cell.textLabel?.textColor = UIColor.darkGray
    cell.textLabel?.font = UIFont(name: "Avenir", size: 17.0)

    cell.textLabel?.text = globalMasterStructArray[indexPath.row].title

    return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.performSegue(withIdentifier: "showDetail", sender: self)
}



// MARK: - Fetched results controller




 // Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed.
/*
 private func controllerDidChangeContent(controller: NSFetchedResultsController) {
     // In the simplest, most efficient, case, reload the table view.
     self.tableView.reloadData()
 }
 */


}
private extension MasterViewController {

func setupPullToRefresh() {
    tableView.addPullToRefresh(PullToRefresh()) { [weak self] in
        let delayTime = DispatchTime.now() + Double(Int64(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
        DispatchQueue.main.asyncAfter(deadline: delayTime) {
            print("cyka")
            self?.tableView.endRefreshing(at: .top)
            //self?.tableView.frame = CGRect(x: 0 , y: 65 , width : 320 , height : screenSize.height)
        }
    }

    tableView.addPullToRefresh(PullToRefresh(position: .bottom)) { [weak self] in
        let delayTime = DispatchTime.now() + Double(Int64(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
        DispatchQueue.main.asyncAfter(deadline: delayTime) {
            print("blyat")
            self?.tableView.reloadData()
            self?.tableView.endRefreshing(at: .bottom)
        }
    }
}

}

Put
setupPullToRefresh()
into
func viewDidAppear(_ animated: Bool)
For me that some solution of problem

9you commented

I'am facing same problem. @nick-melnick 's solution work but initial refresh will be delay.

For me the problem seem to be when I add new elements, so it seems you maybe have to manually update the frame after adding new elements.