ios 没有 UITableViewController 的 UIRefreshControl
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12497940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIRefreshControl without UITableViewController
提问by Keller
Just curious, as it doesn't immediately seem possible, but is there a sneaky way to leverage the new iOS 6 UIRefreshControl
class without using a UITableViewController
subclass?
只是好奇,因为它似乎不可能立即实现,但是有没有一种偷偷摸摸的方法来利用新的 iOS 6UIRefreshControl
类而不使用UITableViewController
子类?
I often use a UIViewController
with a UITableView
subview and conform to UITableViewDataSource
and UITableViewDelegate
rather than using a UITableViewController
outright.
我经常将 aUIViewController
与UITableView
子视图一起使用,并遵循UITableViewDataSource
andUITableViewDelegate
而不是UITableViewController
直接使用。
回答by Keller
On a hunch, and based on DrummerB's inspiration, I tried simply adding a UIRefreshControl
instance as a subview to my UITableView
. And it magically just works!
凭直觉,并基于 DrummerB 的灵感,我尝试简单地将一个UIRefreshControl
实例作为子视图添加到我的UITableView
. 它神奇地起作用了!
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];
This adds a UIRefreshControl
above your table view and works as expected without having to use a UITableViewController
:)
这会UIRefreshControl
在您的表格视图上方添加一个并按预期工作,而无需使用UITableViewController
:)
EDIT: This above still works but as a few have pointed out, there is a slight "stutter" when adding the UIRefreshControl in this manner. A solution to that is to instantiate a UITableViewController, and then setting your UIRefreshControl and UITableView to that, i.e.:
编辑:以上仍然有效,但正如一些人指出的那样,以这种方式添加 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;
回答by Piotr Tomasik
To eliminate the stutter that is caused by the accepted answer, you can assign your UITableView
to a UITableViewController
.
要消除由接受的答案引起的口吃,您可以将您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;
EDIT:
编辑:
A way to add a UIRefreshControl
with no UITableViewController
with no stutter and retain the nice animation after refreshing data on the tableview.
一种在 tableview 上刷新数据后添加UIRefreshControl
noUITableViewController
并且没有口吃并保留漂亮动画的方法。
UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.theTableView addSubview:refreshControl];
[self.theTableView sendSubviewToBack:refreshControl];
Later when handling the refreshed data...
稍后在处理刷新的数据时...
- (void)handleRefresh:(UIRefreshControl *)refreshControl {
[self.theTableView reloadData];
[self.theTableView layoutIfNeeded];
[refreshControl endRefreshing];
}
回答by Tomohisa Takaoka
What you would try is use container view inside ViewController you are using. you can define clean UITableViewController subclass with dedicated tableview and place that in the ViewController.
您将尝试在您正在使用的 ViewController 中使用容器视图。您可以使用专用的 tableview 定义干净的 UITableViewController 子类,并将其放置在 ViewController 中。
回答by DrummerB
Well UIRefreshControl is a UIView subclass, so you can use it on it's own. I'm not sure though how it renders itself. The rendering could simply depend on the frame, but it also could rely on a UIScrollView or the UITableViewController.
那么 UIRefreshControl 是一个 UIView 子类,所以你可以单独使用它。我不确定它是如何呈现的。渲染可以简单地依赖于框架,但它也可以依赖于 UIScrollView 或 UITableViewController。
Either way, it's going to be more of a hack than an elegant solution. I recommend you look into one of the available 3rd party clones or write your own.
无论哪种方式,它都将更像是一个黑客而不是一个优雅的解决方案。我建议您查看可用的第 3 方克隆之一或自己编写。
回答by boliva
Try delaying the call to the refreshControl -endRefresh
method by a fraction of a second after the tableView reloads its contents, either by using NSObject's -performSelector:withObject:afterDelay:
or GCD's dispatch_after
.
尝试-endRefresh
在 tableView 重新加载其内容后,通过使用 NSObject-performSelector:withObject:afterDelay:
或 GCD将调用 refreshControl方法延迟几分之一秒dispatch_after
。
I created a category on UIRefreshControl for this:
我为此在 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
I tested it and this also works on Collection Views. I've noticed that a delay as small as 0.01 seconds is enough:
我测试了它,这也适用于集合视图。我注意到只有 0.01 秒的延迟就足够了:
// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];
回答by Ashok R
IOS 10 Swift 3.0
IOS 10 斯威夫特 3.0
it's simple
这很简单
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
}
}
If you want to learn about iOS 10 UIRefreshControl read here.
如果您想了解 iOS 10 UIRefreshControl,请阅读此处。
回答by cbh2000
Adding the refresh control as a subview creates an empty space above section headers.
添加刷新控件作为子视图会在节标题上方创建一个空白空间。
Instead, I embedded a UITableViewController into my UIViewController, then changed my tableView
property to point towards the embedded one, and viola! Minimal code changes. :-)
相反,我将一个 UITableViewController 嵌入到我的 UIViewController 中,然后将我的tableView
属性更改为指向嵌入的属性,并且中提琴!最少的代码更改。:-)
Steps:
脚步:
- Create a new UITableViewController in Storyboard and embed it into your original UIViewController
- Replace
@IBOutlet weak var tableView: UITableView!
with the one from the newly embedded UITableViewController, as shown below
- 在 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
}
...
}
回答by stakahop
For Swift 2.2 .
对于 Swift 2.2 。
First make UIRefreshControl() .
首先制作 UIRefreshControl() 。
var refreshControl : UIRefreshControl!
In your viewDidLoad() method add:
在您的 viewDidLoad() 方法中添加:
refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Refreshing..")
refreshControl.addTarget(self, action: #selector(YourUIViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refreshControl)
And make refresh function
并制作刷新功能
func refresh(refreshControl: UIRefreshControl) {
// do something ...
// reload tableView
self.tableView.reloadData()
// End refreshing
refreshControl.endRefreshing()
}
回答by Ankit Kumar Gupta
Try this,
尝试这个,
The Above solutions are fine but tableView.refreshControl is available for UITableViewController only, till iOS 9.x and comes in UITableView from iOS 10.x onwards.
上述解决方案很好,但 tableView.refreshControl 仅适用于 UITableViewController,直到 iOS 9.x 并且从 iOS 10.x 开始出现在 UITableView 中。
Written in Swift 3 -
用 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)
回答by psilencer
Here's another solution which is a little different.
这是另一个有点不同的解决方案。
I had to use it because of some view hierarchy issues I had: I was creating some functionality that required passing views around to different places in the view hierarchy, which broken when using a UITableViewController's tableview b/c the tableView is the UITableViewController's root view (self.view) and not just a regular view, it created inconsistent controller / view hierarchies and caused a crash.
由于我遇到的一些视图层次结构问题,我不得不使用它:我正在创建一些需要将视图传递到视图层次结构中的不同位置的功能,当使用 UITableViewController 的 tableview b/c 时,tableView 是 UITableViewController 的根视图( self.view) 而不仅仅是常规视图,它创建了不一致的控制器/视图层次结构并导致崩溃。
Basically create your own subclass of UITableViewController and override loadView to assign self.view a different view, and override the tableView property to return a separate tableview.
基本上创建您自己的 UITableViewController 子类并覆盖 loadView 以分配 self.view 一个不同的视图,并覆盖 tableView 属性以返回一个单独的 tableview。
for example:
例如:
@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
When combined with Keller's solution this will more robust in the sense that the tableView is now a regular view, not a VC's root view, and be more robust against changing view hierarchies. Example of using it this way:
当与 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;
There is another possible use for this:
还有另一种可能的用途:
Since subclassing this way separates self.view from self.tableView, it's possible now to use this UITableViewController as more of a regular controller, and add other subviews to self.view without the oddities of adding subviews to UITableView, so one may considering making their view controllers directly a subclass of UITableViewController instead of having UITableViewController children.
由于子类化这种方式将 self.view 与 self.tableView 分开,现在可以将此 UITableViewController 用作更多的常规控制器,并将其他子视图添加到 self.view,而无需向 UITableView 添加子视图的奇怪之处,因此可以考虑将它们的视图控制器直接是 UITableViewController 的子类,而不是 UITableViewController 子类。
Some things to watch out for:
需要注意的一些事项:
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.
由于我们在不调用 super 的情况下覆盖了 tableView 属性,因此可能需要注意一些事情并在必要时进行处理。例如,在我上面的示例中设置 tableview 不会将 tableview 添加到 self.view 并且不会设置您可能想要做的框架。此外,在这个实现中,当类被实例化时没有给你默认的 tableView,这也是你可以考虑添加的。我不在这里包括它,因为那是个案,而且这个解决方案实际上非常适合 Keller 的解决方案。