没有tableView如何拉动刷新?

How to pull to refresh without tableView?

我有下一个控制器:

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

viewDidLoad 中,我正在尝试在没有 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()
            }
        )
    }

但在我的情况下这个解决方案不起作用,如何解决这个问题?

所以你少了两行代码:

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

var alwaysBounceVertical: Bool // 默认编号。如果 YES 且 bounces 为 YES,即使内容小于边界,也允许垂直拖动。

请试试这个。谢谢

您的方法似乎没有任何问题。

这是一个完整的示例——它添加了一个“全视图”滚动视图,带有一个 200 磅高的红色子视图(因此我们可以看到效果)。

向下拖动时,您应该会看到 UIRefreshControl“微调器”出现。向下拖动足够远,它将调用 updateView() 函数。由于我们没有您的 SyncScheduler 代码,我添加了 2 秒的异步延迟来模拟该过程:

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()
//          }
//      )
        
    }
}