没有UITableViewController的UIRefreshControl

Kel*_*ler 306 objective-c uitableview ios ios6 uirefreshcontrol

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

我经常使用UIViewController一个UITableView子视图,并符合UITableViewDataSourceUITableViewDelegate而不是使用UITableViewController顾左右而言他.

Kel*_*ler 386

在预感中,基于DrummerB的灵感,我尝试简单地将一个UIRefreshControl实例作为子视图添加到我的UITableView.它神奇地起作用!

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

这会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;
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,这是不受支持的行为,将来可能会发生变化.Apple提出的唯一保证就是根据提供的API使用它(在这种情况下` - [UITableViewController setRefreshControl:]`)将继续运行. (48认同)
  • 为了避免在绕过UITableViewController时出现如上所述的"slutter",只需在表视图下添加刷新控件,如下所示:`[_tableView insertSubview:_refreshControl atIndex:0];`.测试iOS 7和8;) (30认同)
  • 通过这个实现,似乎在触发`handleRefresh:`之前,滚动视图的`contentInsets`的值会在瞬间发生意外的变化.其他人是否经历过这种情况或对其进行修复?(是的,我知道这首先是不受支持的!) (18认同)
  • 你真的应该简单地使用容器视图.只需将其视图控制器的类设置为`UITableViewController`的自定义子类,您将"正确地执行". (6认同)
  • 在iOS7(iOS6未知)中,编辑版本工作正常,但关闭并重新打开应用程序时除外.直到第二次刷新时才会播放动画.重新打开应用后第一次刷新,它只是一个完整的圆圈,而不是根据您拉下它的距离增加的圆圈.有修复吗? (3认同)

Pio*_*sik 94

要消除由接受的答案引起的口吃,您可以将您分配UITableView给a 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;
Run Code Online (Sandbox Code Playgroud)

编辑:

添加一个没有断断续续的UIRefreshControlno的方法UITableViewController,并在刷新tableview上的数据后保留漂亮的动画.

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

稍后处理刷新数据时......

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

  • 您甚至不必创建新的UITableView.只需说initWithStyle:existingTableView.style - 然后再执行newTableViewController.tableView = existingTableView并分配refreshControl.把它煮成三行. (7认同)
  • `self.tableView = _tableViewController.tableView;`应该是`_tableViewController.tableView = self.tableView` (4认同)

Tom*_*oka 21

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

  • 确切地说,最干净的方式似乎是添加UITableViewController类型的子视图控制器. (2认同)

Dru*_*erB 18

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

无论哪种方式,它都将是一个黑客而不是一个优雅的解决方案.我建议您查看一个可用的第三方克隆或编写自己的克隆.

ODRefreshControl

在此输入图像描述

SlimeRefresh

在此输入图像描述

  • ODRefreshControl很棒 - 感谢小费!非常简单,并且做到了.当然比Apple更灵活.我永远不明白为什么有人会使用UITableViewController,IMO是整个API中最差的类.它确实(旁边)没有,但让你的观点不灵活. (7认同)

bol*_*iva 7

-endRefresh在tableView重新加载其内容后,尝试通过使用NSObject -performSelector:withObject:afterDelay:或GCD 延迟对refreshControl 方法的调用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
Run Code Online (Sandbox Code Playgroud)

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

// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];
Run Code Online (Sandbox Code Playgroud)

  • 延迟和等待是非常糟糕的风格. (4认同)
  • @orkoden我同意.这是已经不支持使用`UIRefreshControl`的解决方法. (2认同)
  • 最终效果完全相同,并且不会使"黑客"变得更加/不那么优雅.是否使用`-performSelector:withObject:afterDelay:`或GCD,这取决于个人品味. (2认同)

Ash*_*k R 6

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
    }

}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您想了解iOS 10 UIRefreshControl,请阅读此处.