当我返回到视图控制器时,如何在表格视图顶部实现刷新控件?

7

因为某些原因,第一次加载视图控制器时,刷新控件的行为符合预期(即,在向下滑动时显示在表格视图下方)。问题是当我点击另一个选项卡,然后返回到视图控制器时,刷新控件不再淡入,而是可见于表格视图之上。

When I go back to view controller

这是代码的一部分:

class CoreTableViewController : UIViewController, UITableViewDataSource, UITableViewDelegate {

var tableView:UITableView!
var tableData:Array<AnyObject> = []
var dataFetched:Bool = false
var refreshControl:UIRefreshControl?

override func viewDidLoad() {
    super.viewDidLoad()

    self.edgesForExtendedLayout = UIRectEdge.None;

    self.tableView = self.assignTableView()
    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None;

    if self.enableRefresher() {
        self.setRefreshControl()
    }
}

func enableRefresher() -> Bool {
    return true
}

func fetchData(cleanFirst:Bool = false) {
    // Fetch data.
}

func refresh() {
    self.fetchData(true)
    self.refreshControl!.endRefreshing()
}

func setRefreshControl() {
    self.refreshControl = UIRefreshControl()
    //self.refreshControl!.attributedTitle = NSAttributedString(string: "Actualizar")
    self.refreshControl!.addTarget(self, action: #selector(CoreTableViewController.refresh), forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refreshControl!)
}

}

任何想法?

请明确阐述,我不明白你想要什么和你得到了什么。 - Amit Singh
11个回答

11

尝试将z索引设置为-1,这意味着UIRefreshControl在任何视图的后面。

refreshControl.layer.zPosition = -1

tableView.refreshControl?.beginRefreshing()
self.tableView.refreshControl?.endRefreshing()

两者必须成对使用。


这对我很有帮助,谢谢! - xlsmearlx

10
我在这里找到了解决方法:https://stackoverflow.com/a/29088409/209200 应该使用self.tableView.insertSubview(refreshControl!, atIndex: 0)而不是self.tableView.addSubview(refreshControl!)
这导致刷新控件出现在表格视图上方。

1
即使如此,在iOS 11.x上,refreshesControl仍然显示在表格之上(iOS 9正常工作)。 - Mando
iOS 11上存在模拟器错误,但设备正常工作。 - bpolat

4

将刷新控件插入到索引0处并不起作用,只需将其设置为tableView的背景视图:

tableView.backgroundView = refreshControl

2
太棒了!这正是我在寻找的 - 谢谢! - Nicolai Harbo

3

尝试这个:

上述的解决方案还不错,但tableView.refreshControl仅适用于UITableViewController,在iOS 9.x之前可用,在iOS 10.x及以后版本中也适用于UITableView。

要解决此问题,只需使用以下代码:

Swift 3代码示例:

let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(FeedViewController.loadNewData), for: UIControlEvents.valueChanged)
// Fix for the RefreshControl Not appearing in background
tableView?.addSubview(refreshControl)
tableView.sendSubview(toBack: refreshControl)

0

在我检查了您的代码和问题后,我认为问题出在这里:

"除了将刷新控件分配给表视图控制器的refreshControl属性之外,您还必须配置控件本身的目标和操作。" https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIRefreshControl_class/index.html#//apple_ref/occ/instm/UIRefreshControl/endRefreshing

因此,根据文档,您需要使用UITableViewController,而不是UIViewController,并设置其refreshControl属性。

在当前状态下,您只需将UIRefreshControl添加为常规子视图。


如果您想使用集合视图怎么办?我在集合视图中使用刷新控件时遇到了完全相同的问题。 - Ricardo
@Ricardo,看看集合视图文档吧。看起来UIRefreshControl专门为UITableView设计。也许你需要浏览已实现的解决方案或自己制作...无论如何,这是一个不同问题的话题。 - Dima Deplov

0

对我来说,使用在表视图的0号索引处插入并像懒惰变量一样初始化是有效的:

  private lazy var refreshControl: UIRefreshControl = {
        let refreshControl = UIRefreshControl()
        refreshControl.tintColor = .gray
        refreshControl.addTarget(self, action: #selector(refreshFollowingList(_:)), for: .valueChanged)
        return refreshControl
    }()

    func setupRefresher() {
        self.tableView.insertSubview(refreshControl, at: 0)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        setupRefresher()
    }

如果我只是将表视图的刷新控件分配给了懒变量,它会在内容偏移109像素时跳动20个像素,所以我像这样修复它。我正在使用UIViewController而不是UITableViewController,希望这可以帮助。


0

不幸的是,以上没有任何一种解决方案能够帮助我。

在我的情况下,当表视图为空时重新加载表视图后会出现刷新控件。也许如果表视图至少有一行,它就会简单地隐藏刷新控件,我还没有检查过。此外,当我的视图控制器再次出现时,它会像一个解决方法一样工作,并隐藏刷新控件。

但我已经找到了另一个立即隐藏刷新控件的解决方法。这里必须使用异步调用。

tableView.reloadData()
DispatchQueue.main.async {
  refreshControl.endRefreshing()
}

我受到this在另一篇帖子中的回答的启发。

0

看起来还好,我怀疑这是由于控件本身创建方面的某些竞争条件。我发现在这种情况下使用惰性属性会有很大帮助。我会像这样做:

lazy var refreshControl: UIRefreshControl = {
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action:#selector(CoreTableViewController.refresh(_:)), forControlEvents: .ValueChanged)
    return refreshControl
}()

override public func viewDidLoad() {
    super.viewDidLoad()
    if self.enableRefresher() {
        tableView.addSubview(refreshControl)
    }
    ........
}

func refresh(refreshControl: UIRefreshControl) {
    self.fetchData(true)
    refreshControl.endRefreshing()
}

您不需要使用TableViewController,UIViewController就足够了,而且往往更灵活。

希望这有所帮助。


0

UIRefreshControl 的容器视图类似于 UIView,您还应该设置 isOpaque = trueclipToBounds = true

private lazy var refreshControl: UIRefreshControl = {
    let refreshControl = UIRefreshControl(frame: .zero)
    refreshControl.isOpaque = true
    refreshControl.clipsToBounds = true
    refreshControl.backgroundColor = .black
    refreshControl.addTarget(self, action: #selector(self.refresh(_:)), for: .valueChanged)
    return refreshControl
}()

0
我们需要进行简单的配置,将UIRefreshControl分配给tableView,如下所示。
@IBOutlet weak var tableView : UITableView! {
    didSet {
        tableView.dataSource = self
        tableView.delegate = self
        tableView.refreshControl = UIRefreshControl()
        tableView.refreshControl?.addTarget(self, action: #selector(handleRefresh(_:)), for: UIControl.Event.valueChanged)

    }
}

现在添加handleRefresh方法来处理你的逻辑

@objc
func handleRefresh(_ refreshControl: UIRefreshControl) {
    // Here i am disabling the user interaction while refreshing
    tableView.alpha = 0.5        
    self.view.isUserInteractionEnabled = false
    // Get your work done here

    // At the end stop the refresh control and enable user interaction again.      
    tableView.refreshControl?.endRefreshing()
    tableView.alpha = 1.0        
    self.view.isUserInteractionEnabled = true
}

现在,当您从另一个标签返回时,刷新控件会停止旋转。因此,为了处理这个问题,请添加以下代码行...
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // Here we are forcefully end refreshing and again starting, as we know it works when we scroll down the table. We are doing it programmatically.
    if tableView.refreshControl!.isRefreshing {
        let contentOffset = tableView.contentOffset
        tableView.refreshControl?.endRefreshing()
        tableView.refreshControl?.beginRefreshing()
        tableView.contentOffset = contentOffset
    }
} 

希望这将对人们有所帮助 :-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接