有点好奇,因为似乎不太可能,但是是否有一种隐蔽的方法可以利用新的iOS 6 UIRefreshControl
类而不使用UITableViewController
子类呢?
我经常使用一个带有UITableView
子视图的UIViewController
,并符合UITableViewDataSource
和UITableViewDelegate
,而不是直接使用UITableViewController
。
有点好奇,因为似乎不太可能,但是是否有一种隐蔽的方法可以利用新的iOS 6 UIRefreshControl
类而不使用UITableViewController
子类呢?
我经常使用一个带有UITableView
子视图的UIViewController
,并符合UITableViewDataSource
和UITableViewDelegate
,而不是直接使用UITableViewController
。
基于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;
-[UITableViewController setRefreshControl:]
)使用它将继续正常运行。 - Dave DeLonghandleRefresh:
前,滚动视图的 contentInsets
会在一瞬间发生意外变化。还有其他人遇到过这种情况或者知道如何解决吗?(是的,我知道这本来就不被支持!) - TimUITableViewController
子类,就能够“正确地”实现它。 - Eugene[_tableView insertSubview:_refreshControl atIndex:0];
。在iOS 7和8上进行了测试;) - Stephen VinouzeUITableView
分配给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;
编辑:
一种在没有UITableViewController
的情况下添加UIRefreshControl
的方法,没有卡顿,并且在刷新表视图数据后保留良好的动画效果。
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];
}
[_tablewViewController didMoveToParentViewController:self];
。 - qix_tableViewController.tableView = self.tableView;
,这行代码的作用是将_tableViewController
对象中的tableView
属性设置为当前对象(self
)中的tableView
属性。 - Aliself.childViewControllers.firstObject
获取 UITableViewController。 - cbh2000prepareForSegue
方法来获取容器视图中的 UITableViewController 对象的引用,因为它会在从故事板实例化时立即触发作为一个 segue 事件。 - crarhoUIRefreshControl 是 UIView 的子类,因此您可以单独使用它。但我不确定它是如何渲染自己的。渲染可能仅取决于框架,但也可能依赖于 UIScrollView 或 UITableViewController。
无论哪种方式,都更像是一种 hack 而不是优雅的解决方案。建议您使用可用的第三方克隆之一或编写自己的刷新控件。
@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];
UIRefreshControl
使用的一种解决方法。 - boliva[self performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.01]
更轻松地延迟调用一个方法。 - orkoden-performSelector:withObject:afterDelay:
还是GCD取决于个人口味。 - bolivaiOS 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的相关内容,请阅读这里。
tableView
属性更改为指向嵌入的那个,完美!代码改动最小:)@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!
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()
}
这里有另一种略微不同的解决方案。
我不得不使用它,因为我遇到了一些视图层次结构问题:我正在创建一些需要将视图传递到视图层次结构中不同位置的功能,在使用UITableViewController的tableview时会出现问题,因为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子类。
需要注意的一些事项:
由于我们覆盖了tableView属性而没有调用super,因此可能需要注意一些事项,并在必要时进行处理。例如,在上面的示例中设置tableview将不会将tableview添加到self.view并设置其框架,您可能希望这样做。此外,在此实现中,当类被实例化时,没有默认的tableView提供给您,这也是您可能要考虑添加的内容。我没有在这里包括它,因为那是具体情况,而且这个解决方案实际上与Keller的解决方案非常匹配。
试试这个:
上面的解决方案不错,但是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)
UITableViewController
,并提交一个bug请求API直接在UITableView
中使用UIRefreshControl
。 - Dave DeLong