只是好奇,因为它不立即看起来可能,但有一种狡猾的方式来利用新的iOS 6 UIRefreshControl类而不使用UITableViewController子类吗?

我经常使用带有UITableView子视图的UIViewController,并符合UITableViewDataSource和UITableViewDelegate,而不是直接使用UITableViewController。


UIRefreshControl是一个UIView子类,你可以单独使用它。但我不确定它是如何呈现的。渲染可以简单地依赖于帧,但它也可以依赖于UIScrollView或UITableViewController。

无论哪种方式,它都将是一种hack而不是优雅的解决方案。我建议你找一个第三方的克隆版本,或者自己写一个。

ODRefreshControl

SlimeRefresh

基于直觉,基于DrummerB的灵感,我尝试简单地添加一个UIRefreshControl实例作为子视图到我的UITableView。它神奇地工作了!

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];

这添加了一个UIRefreshControl在你的表视图和工作的预期,而不需要使用UITableViewController:)


编辑:上面的方法仍然有效,但正如一些人指出的那样,当以这种方式添加UIRefreshControl时,会有轻微的“口吃”。一个解决方案是实例化一个UITableViewController,然后设置你的UIRefreshControl和UITableView,即:

UITableViewController *tableViewController = [[UITableViewController alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;

你要尝试的是在ViewController中使用容器视图。你可以用专用的tableview定义干净的UITableViewController子类并把它放在ViewController中。

为了消除由接受的答案引起的口吃,你可以将你的UITableView分配给一个UITableViewController。

_tableViewController = [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
[self addChildViewController:_tableViewController];

_tableViewController.refreshControl = [UIRefreshControl new];
[_tableViewController.refreshControl addTarget:self action:@selector(loadStream) forControlEvents:UIControlEventValueChanged];

_theTableView = _tableViewController.tableView;

编辑:

一种添加UIRefreshControl的方法,没有UITableViewController,没有口吃,并在刷新tableview上的数据后保留漂亮的动画。

UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.theTableView addSubview:refreshControl];
[self.theTableView sendSubviewToBack:refreshControl];

稍后在处理刷新数据时…

- (void)handleRefresh:(UIRefreshControl *)refreshControl {
    [self.theTableView reloadData];
    [self.theTableView layoutIfNeeded];
    [refreshControl endRefreshing];
}

尝试在tableView重新加载其内容后延迟调用refreshControl -endRefresh方法几分之一秒,可以使用NSObject的-performSelector:withObject:afterDelay:或GCD的dispatch_after。

我在UIRefreshControl上创建了一个类别:

@implementation UIRefreshControl (Delay)

- (void)endRefreshingAfterDelay:(NSTimeInterval)delay {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self endRefreshing];
    });
}

@end

我测试了它,这也适用于集合视图。我注意到,一个小到 0.01秒就足够了:

// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];

事实证明,当你使用带有UITableView子视图的UIViewController并遵循UITableViewDataSource和UITableViewDelegate时,你可以使用以下方法:

self.refreshControl = [[UIRefreshControl alloc]init];
[self.refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];

Keller的第一个建议在iOS 7中导致了一个奇怪的错误,即在视图控制器重新出现后,表的插入增加了。换到第二个答案,使用uitableviewcontroller,为我解决了问题。

这是另一个有点不同的解决方案。

我不得不使用它,因为我有一些视图层次结构问题:我正在创建一些功能,需要将视图传递到视图层次结构中的不同地方,当使用UITableViewController的tableview b/c时,tableview是UITableViewController的根视图(self.view),而不仅仅是常规视图,它创建了不一致的控制器/视图层次结构,并导致崩溃。

基本上创建你自己的UITableViewController的子类并重写loadView来赋值self。查看一个不同的视图,并重写tableView属性以返回一个单独的tableView。

例如:

@interface MyTableVC : UITableViewController
@end

@interface MyTableVC ()
@property (nonatomic, strong) UITableView *separateTableView;
@end

@implementation MyTableVC

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:CGRectZero];
}

- (UITableView *)tableView {
    return self.separateTableView;
}

- (void)setTableView:(UITableView *)tableView {
    self.separateTableView = tableView;
}

@end

当与Keller的解决方案相结合时,这将更加健壮,因为tableView现在是一个常规视图,而不是VC的根视图,并且对视图层次结构的变化更加健壮。这样使用它的例子:

MyTableVC *tableViewController = [[MyTableVC alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;

还有另一个可能的用法:

因为子类化这样分离了self。从自我角度看。tableView,现在可以使用这个UITableViewController作为更常规的控制器,并添加其他子视图到self。视图,而不需要给UITableView添加子视图,所以你可以考虑让他们的视图控制器直接成为UITableViewController的子类,而不是有UITableViewController的子类。

一些需要注意的事情:

Since we're overriding the tableView property without calling super, there may be some things to watch out for and should handle where necessary. For example, setting the tableview in my above example will not add the tableview to self.view and not set the frame which you may want to do. Also, in this implementation there is no default tableView given to you when the class is instantiated, which is also something you may consider adding. I don't include it here because that is case by case, and this solution actually fits well with Keller's solution.

将刷新控件添加为子视图将在节头上方创建一个空白区域。

相反,我嵌入了一个UITableViewController到我的UIViewController中,然后改变我的tableView属性指向嵌入的那个,viola!最小的代码更改。: -)

步骤:

在Storyboard中创建一个新的UITableViewController并将其嵌入到你原来的UIViewController中 替换@IBOutlet weak var tableView: UITableView!与新嵌入的UITableViewController中的一个,如下所示


class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableViewController = self.childViewControllers.first as! UITableViewController
        tableView = tableViewController.tableView
        tableView.dataSource = self
        tableView.delegate = self

        // Now we can (properly) add the refresh control
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: "handleRefresh:", forControlEvents: .ValueChanged)
        tableViewController.refreshControl = refreshControl
    }

    ...
}

对于Swift 2.2。

首先创建UIRefreshControl()。

var refreshControl : UIRefreshControl!

在你的viewDidLoad()方法中添加:

refreshControl = UIRefreshControl()
    refreshControl.attributedTitle = NSAttributedString(string: "Refreshing..")
    refreshControl.addTarget(self, action: #selector(YourUIViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refreshControl)

并创建refresh函数

func refresh(refreshControl: UIRefreshControl) {

    // do something ...

    // reload tableView
    self.tableView.reloadData()

    // End refreshing
    refreshControl.endRefreshing()
}

试试这个,

上述解决方案是很好的,但tableView。refreshControl只适用于UITableViewController,直到iOS 9。x,来自iOS 10的UITableView。x开始。

写在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)

IOS 10 Swift 3.0

它很简单

import UIKit

class ViewControllerA: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var myTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myTableView.delegate = self
        myTableView.dataSource = self

        if #available(iOS 10.0, *) {
            let refreshControl = UIRefreshControl()
            let title = NSLocalizedString("PullToRefresh", comment: "Pull to refresh")
            refreshControl.attributedTitle = NSAttributedString(string: title)
            refreshControl.addTarget(self,
                                     action: #selector(refreshOptions(sender:)),
                                     for: .valueChanged)
            myTableView.refreshControl = refreshControl
        }
    }

    @objc private func refreshOptions(sender: UIRefreshControl) {
        // Perform actions to refresh the content
        // ...
        // and then dismiss the control
        sender.endRefreshing()
    }

    // MARK: - Table view data source

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

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 12
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        cell.textLabel?.text = "Cell \(String(indexPath.row))"
        return cell
    }

}

如果你想了解iOS 10 UIRefreshControl,请阅读这里。