308

只是好奇,因为它似乎不可能立即实现,但是有没有一种偷偷摸摸的方法来利用新的 iOS 6UIRefreshControl类而不使用UITableViewController子类?

我经常将 aUIViewControllerUITableView子视图一起使用,并遵循UITableViewDataSourceUITableViewDelegate不是UITableViewController直接使用。

4

12 回答 12

388

凭直觉,根据 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;
于 2012-09-19T20:32:48.213 回答
94

要消除由接受的答案引起的口吃,您可以将您的分配UITableViewUITableViewController.

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

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

_theTableView = _tableViewController.tableView;

编辑:

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

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];
}
于 2013-01-03T22:14:03.170 回答
21

您将尝试在您正在使用的 ViewController 中使用容器视图。您可以使用专用的 tableview 定义干净的 UITableViewController 子类并将其放置在 ViewController 中。

于 2012-10-25T21:09:31.120 回答
18

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

无论哪种方式,它都将更像是一种 hack,而不是一种优雅的解决方案。我建议您查看可用的第 3 方克隆之一或编写自己的。

ODRefreshControl

在此处输入图像描述

史莱姆刷新

在此处输入图像描述

于 2012-09-19T15:38:46.483 回答
7

尝试在 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];
于 2013-08-03T04:48:41.250 回答
7

IOS 10 斯威夫特 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,请阅读此处

于 2016-12-22T15:49:46.610 回答
3

将刷新控件添加为子视图会在部分标题上方创建一个空白区域。

相反,我将一个 UITableViewController 嵌入到我的 UIViewController 中,然后将我的tableView属性更改为指向嵌入的那个,中提琴!最少的代码更改。:-)

脚步:

  1. 在 Storyboard 中创建一个新的 UITableViewController 并将其嵌入到您原来的 UIViewController 中
  2. 替换@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
    }

    ...
}
于 2015-03-05T05:46:11.447 回答
2

对于斯威夫特 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)

并制作刷新功能

func refresh(refreshControl: UIRefreshControl) {

    // do something ...

    // reload tableView
    self.tableView.reloadData()

    // End refreshing
    refreshControl.endRefreshing()
}
于 2016-05-17T20:06:31.170 回答
0

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

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

基本上创建自己的 UITableViewController 子类并覆盖 loadView 以分配 self.view 不同的视图,并覆盖 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.view 与 self.tableView 分开,因此现在可以将此 UITableViewController 用作更多常规控制器,并将其他子视图添加到 self.view 而不会向 UITableView 添加子视图,因此可能会考虑制作他们的视图控制器直接是 UITableViewController 的子类,而不是 UITableViewController 子类。

需要注意的一些事项:

由于我们在不调用 super 的情况下覆盖 tableView 属性,因此可能需要注意一些事情,并在必要时进行处理。例如,在我上面的示例中设置 tableview 不会将 tableview 添加到 self.view 并且不会设置您可能想要做的框架。此外,在这个实现中,当类被实例化时,没有默认的 tableView 给你,这也是你可以考虑添加的东西。我不在这里包括它,因为这是个案,这个解决方案实际上非常适合 Keller 的解决方案。

于 2014-01-08T21:36:36.907 回答
0

试试这个,

上述解决方案很好,但 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)
于 2016-12-12T05:12:07.737 回答
-1

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

于 2013-09-25T11:13:01.277 回答
-6

事实证明,当您将 UIViewController 与 UITableView 子视图一起使用并符合 UITableViewDataSource 和 UITableViewDelegate 时,您可以使用以下内容:

self.refreshControl = [[UIRefreshControl alloc]init];
[self.refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
于 2013-09-14T17:25:15.143 回答