我正在使用swift构建一个RSS阅读器,需要实现重新加载功能。

以下是我如何努力做到这一点。

class FirstViewController: UIViewController,
    UITableViewDelegate, UITableViewDataSource {

   @IBOutlet var refresh: UIScreenEdgePanGestureRecognizer
   @IBOutlet var newsCollect: UITableView

   var activityIndicator:UIActivityIndicatorView? = nil

   override func viewDidLoad() {
       super.viewDidLoad()
       self.newsCollect.scrollEnabled = true
      // Do any additional setup after loading the view, typically from a nib.

      if nCollect.news.count <= 2{
          self.collectNews()
       }
      else{
          self.removeActivityIndicator()
       }
      view.addGestureRecognizer(refresh)
   }



@IBAction func reload(sender: UIScreenEdgePanGestureRecognizer) {
    nCollect.news = News[]()
    return newsCollect.reloadData()
}

我得到:

财产的自我。刷新'未在super初始化。init调用

请帮助我理解手势识别器的行为。一个工作样例代码将是一个很大的帮助。

谢谢。


当前回答

我建议在每个类中使用pull to Refresh的扩展。

1)创建一个空的swift文件:文件-新建-文件- swift文件。

2)添加以下内容

    //  AppExtensions.swift

    import Foundation
    import UIKit    

    var tableRefreshControl:UIRefreshControl = UIRefreshControl()    

    //MARK:- VIEWCONTROLLER EXTENSION METHODS
    public extension UIViewController
    {
        func makePullToRefreshToTableView(tableName: UITableView,triggerToMethodName: String){

            tableRefreshControl.attributedTitle = NSAttributedString(string: "TEST: Pull to refresh")
            tableRefreshControl.backgroundColor = UIColor.whiteColor()
            tableRefreshControl.addTarget(self, action: Selector(triggerToMethodName), forControlEvents: UIControlEvents.ValueChanged)
            tableName.addSubview(tableRefreshControl)
        }
        func makePullToRefreshEndRefreshing (tableName: String)
        {
            tableRefreshControl.endRefreshing()
//additional codes

        }
    }    

3)在你的视图控制器中调用这些方法:

  override func viewWillAppear(animated: Bool) {

self.makePullToRefreshToTableView(bidderListTable, triggerToMethodName: "pullToRefreshBidderTable")
}

4)在某些时候,你想要结束刷新:

  func pullToRefreshBidderTable() {
self.makePullToRefreshEndRefreshing("bidderListTable")    
//Code What to do here.
}
OR    
self.makePullToRefreshEndRefreshing("bidderListTable")

其他回答

UIRefreshControl直接支持在每个UICollectionView, UITableView和UIScrollView(需要iOS 10+)!

这些视图中的每一个都有一个refreshControl实例属性,这意味着不再需要在你的滚动视图中添加它作为子视图,你所要做的就是:

@IBOutlet weak var collectionView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(doSomething), for: .valueChanged)
    
    // this is the replacement of implementing: "collectionView.addSubview(refreshControl)"
    collectionView.refreshControl = refreshControl
}

@objc func doSomething(refreshControl: UIRefreshControl) {
    print("Hello World!")
    
    // somewhere in your code you might need to call:
    refreshControl.endRefreshing()
}

就我个人而言,我觉得将它作为滚动视图的属性比将它作为子视图添加更自然,特别是因为唯一合适的视图作为UIRefreshControl的父视图是一个滚动视图,即使用UIRefreshControl的功能只在与滚动视图一起工作时有用;这就是为什么这种方法应该更明显地设置刷新控件视图。

但是,你仍然可以选择基于iOS版本使用addSubview:

if #available(iOS 10.0, *) {
  collectionView.refreshControl = refreshControl
} else {
  collectionView.addSubview(refreshControl)
}

你可以使用tableView的子类:

import UIKit

protocol PullToRefreshTableViewDelegate : class {
    func tableViewDidStartRefreshing(tableView: PullToRefreshTableView)
}

class PullToRefreshTableView: UITableView {

    @IBOutlet weak var pullToRefreshDelegate: AnyObject?
    private var refreshControl: UIRefreshControl!
    private var isFirstLoad = true

    override func willMoveToSuperview(newSuperview: UIView?) {
        super.willMoveToSuperview(newSuperview)

        if (isFirstLoad) {
            addRefreshControl()
            isFirstLoad = false
        }
    }

    private func addRefreshControl() {
        refreshControl = UIRefreshControl()
        refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
        refreshControl.addTarget(self, action: "refresh", forControlEvents: .ValueChanged)
        self.addSubview(refreshControl)
    }

    @objc private func refresh() {
       (pullToRefreshDelegate as? PullToRefreshTableViewDelegate)?.tableViewDidStartRefreshing(self)
    }

    func endRefreshing() {
        refreshControl.endRefreshing()
    }

}

1 -在接口构建器改变类你的tableView PullToRefreshTableView或创建一个PullToRefreshTableView编程

在你的视图控制器中实现PullToRefreshTableViewDelegate

当表视图开始刷新时,tableViewDidStartRefreshing(tableView: PullToRefreshTableView)将在视图控制器中被调用

4 -调用yourTableView.endRefreshing()来完成刷新

func pullToRefresh(){

    let refresh = UIRefreshControl()
    refresh.addTarget(self, action: #selector(handleTopRefresh(_:)), for: .valueChanged )
    refresh.tintColor = UIColor.appBlack
    self.tblAddressBook.addSubview(refresh)

}
@objc func handleTopRefresh(_ sender:UIRefreshControl){
    self.callAddressBookListApi(isLoaderRequired: false)
    sender.endRefreshing()
}

这个错误告诉你,刷新没有初始化。注意,你选择使refresh不是可选的,这在Swift中意味着它必须在调用super之前有一个值。Init(或者隐式调用,这似乎是你的情况)。要么使刷新是可选的(可能是你想要的),要么以某种方式初始化它。

我建议你再读一遍Swift的介绍文档,里面详细地介绍了这一点。

最后,正如@Anil指出的,iOS中有一个内置的名为UIRefresControl的拉刷新控件,这可能是值得研究的东西。

由于可定制性较差,代码重复和刷新控件带来的错误,我创建了一个库PullToRefreshDSL,它使用DSL模式,就像SnapKit一样

// You only have to add the callback, rest is taken care of
tableView.ptr.headerCallback = { [weak self] in // weakify self to avoid strong reference
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { // your network call
        self?.tableView.ptr.isLoadingHeader = false // setting false will hide the view
    }
}

你只需要在任何UIScrollView子类后添加神奇的关键字ptr,即UITableView/UICollectionView

你不需要下载库,你可以探索和修改源代码,我只是指向一个可能的实现拉动刷新iOS