Morozov
Morozov

Reputation: 5250

How to pull to refresh without tableView?

I have next controller:

final class CategoryBreakdownViewController: UIViewController {
  
    private let scrollView = UIScrollView(alwaysBounceVertical: true)
    var refreshControl = UIRefreshControl()

Where in viewDidLoad I'm trying to implement pull to refresh without tableView:

 private func setupRefreshControl() {    
        scrollView.alwaysBounceVertical = true
        scrollView.bounces  = true
        refreshControl.addTarget(self, action: #selector(updateView), for: .valueChanged)
        self.scrollView.addSubview(refreshControl)
    }
    
    @objc func updateView() {
        SyncScheduler.syncImmediately(
            success: {
                self.refreshControl.endRefreshing()
            },
            failure: { [weak self] errorMessage in
                self?.present(message: errorMessage, style: .error)
                self?.refreshControl.endRefreshing()
            }
        )
    }

But in my case this solution doesn't worked, how to solve this problem?

Upvotes: 0

Views: 655

Answers (2)

Kudos
Kudos

Reputation: 1490

So you are missing two line of code:

self.scrollView.scrollEnabled = true
self.scrollView.alwaysBounceVertical = true

var alwaysBounceVertical: Bool // default NO. if YES and bounces is YES, even if content is smaller than bounds, allow drag vertically.

Please try this. Thanks

Upvotes: 0

DonMag
DonMag

Reputation: 77462

There doesn't appear to be anything wrong with your approach.

Here is a complete example -- it adds a "full view" scrollView, with a 200-pt tall red subview (so we can see the effect).

When you drag down, you should see the UIRefreshControl "spinner" appear. Drag down far enough, and it will call the updateView() func. Since we don't have your SyncScheduler code, I added a 2-second async delay to simulate the process:

final class CategoryBreakdownViewController: UIViewController {
    
    private let scrollView = UIScrollView()
    var refreshControl = UIRefreshControl()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        scrollView.backgroundColor = .systemTeal
        scrollView.translatesAutoresizingMaskIntoConstraints = false

        let testView = UIView()
        testView.backgroundColor = .red
        testView.translatesAutoresizingMaskIntoConstraints = false

        scrollView.addSubview(testView)
        view.addSubview(scrollView)
    
        let contentGuide = scrollView.contentLayoutGuide
        let frameGuide = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            
            testView.topAnchor.constraint(equalTo: contentGuide.topAnchor, constant: 20.0),
            testView.leadingAnchor.constraint(equalTo: contentGuide.leadingAnchor, constant: 20.0),
            testView.trailingAnchor.constraint(equalTo: contentGuide.trailingAnchor, constant: -20.0),
            testView.bottomAnchor.constraint(equalTo: contentGuide.bottomAnchor, constant: -20.0),

            testView.widthAnchor.constraint(equalTo: frameGuide.widthAnchor, constant: -40.0),
            testView.heightAnchor.constraint(equalToConstant: 200.0),
        ])

        setupRefreshControl()
    }
    
    private func setupRefreshControl() {
        scrollView.alwaysBounceVertical = true
        scrollView.bounces = true
        refreshControl.addTarget(self, action: #selector(updateView), for: .valueChanged)
        self.scrollView.addSubview(refreshControl)
    }
    
    @objc func updateView() {

        // simulate a background process that takes 2 seconds
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0, execute: {
            self.refreshControl.endRefreshing()
        })
        
//      SyncScheduler.syncImmediately(
//          success: {
//              self.refreshControl.endRefreshing()
//          },
//          failure: { [weak self] errorMessage in
//              self?.present(message: errorMessage, style: .error)
//              self?.refreshControl.endRefreshing()
//          }
//      )
        
    }
}

Upvotes: 1

Related Questions