Curieux, cela ne semble pas immédiatement possible, mais existe-t-il un moyen sournois de tirer parti de la nouvelle classe iOS 6 UIRefreshControl
sans utiliser de sous-classe UITableViewController
?
J'utilise souvent un UIViewController
avec un UITableView
et je me conforme à UITableViewDataSource
et UITableViewDelegate
plutôt que d'utiliser un UITableViewController
.
Inspiré de DrummerB, j’ai simplement essayé d’ajouter une instance UIRefreshControl
en tant que sous-vue de mon UITableView
. Et cela fonctionne comme par magie!
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];
Cela ajoute un UIRefreshControl
au-dessus de la vue de votre table et fonctionne comme prévu sans avoir à utiliser un UITableViewController
:)
EDIT: Ceci ci-dessus fonctionne toujours, mais comme quelques-uns l’ont signalé, il y a un léger "bégaiement" lorsqu’on ajoute le UIRefreshControl de cette manière. Une solution consiste à instancier un UITableViewController, puis à définir votre UIRefreshControl et votre UITableView, c’est-à-dire:
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;
Pour éliminer le bégaiement causé par la réponse acceptée, vous pouvez affecter votre UITableView
à un 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:
Une façon d'ajouter une UIRefreshControl
sans UITableViewController
sans bégayer et de conserver l'animation de Nice après l'actualisation des données dans la vue de table.
UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.theTableView addSubview:refreshControl];
[self.theTableView sendSubviewToBack:refreshControl];
Plus tard, lors du traitement des données actualisées ...
- (void)handleRefresh:(UIRefreshControl *)refreshControl {
[self.theTableView reloadData];
[self.theTableView layoutIfNeeded];
[refreshControl endRefreshing];
}
Ce que vous voudriez essayer, c’est d’utiliser la vue conteneur dans ViewController que vous utilisez. vous pouvez définir une sous-classe propre UITableViewController avec une vue de table dédiée et la placer dans ViewController.
Eh bien, UIRefreshControl est une sous-classe UIView, vous pouvez donc l'utiliser seule. Je ne sais pas comment ça se rend. Le rendu pourrait simplement dépendre du cadre, mais il pourrait également s'appuyer sur UIScrollView ou UITableViewController.
Dans les deux cas, ce sera plus un bidouillage qu'une solution élégante. Je vous recommande d’examiner un des clones tiers disponibles ou d’écrire le vôtre.
Essayez de retarder l'appel de la méthode refreshControl -endRefresh
d'une fraction de seconde après le chargement du tableau dans son contenu, soit à l'aide de -performSelector:withObject:afterDelay:
de NSObject, soit de dispatch_after
de GCD.
J'ai créé une catégorie sur UIRefreshControl pour cela:
@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
Je l'ai testé et cela fonctionne également sur les vues de collection. J'ai remarqué qu'un délai aussi petit que 0,01 seconde est suffisant:
// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];
IOS 10 Swift 3.0
c'est 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
}
}
Si vous souhaitez en savoir plus sur iOS 10 UIRefreshControl, lisez ici .
L'ajout du contrôle d'actualisation en tant que sous-vue crée un espace vide au-dessus des en-têtes de section.
Au lieu de cela, j'ai incorporé un UITableViewController dans mon UIViewController, puis modifié ma propriété tableView
pour qu'elle pointe vers celui qui est incorporé, et alto! Changements de code minimaux. :-)
Pas:
@IBOutlet weak var tableView: UITableView!
par celui du nouveau UITableViewController, comme indiqué ci-dessous.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
}
...
}
Pour Swift 2.2.
Commencez par créer UIRefreshControl ().
var refreshControl : UIRefreshControl!
Dans votre méthode viewDidLoad (), ajoutez:
refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Refreshing..")
refreshControl.addTarget(self, action: #selector(YourUIViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refreshControl)
Et rendre la fonction de rafraîchissement
func refresh(refreshControl: UIRefreshControl) {
// do something ...
// reload tableView
self.tableView.reloadData()
// End refreshing
refreshControl.endRefreshing()
}
Essaye ça,
Les solutions ci-dessus conviennent, mais tableView.refreshControl est disponible uniquement pour UITableViewController, jusqu'à iOS 9.x et dans UITableView à partir de iOS 10.x.
Écrit en 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)
Voici une autre solution qui est un peu différente.
Je devais l'utiliser à cause de certains problèmes de hiérarchie de vues: je créais certaines fonctionnalités qui nécessitaient de transmettre des vues à différents endroits de la hiérarchie, interrompues lors de l'utilisation d'une vue de table UITableViewController car la vue de table était la vue racine de UITableViewController ( auto.view) et pas seulement une vue régulière, il a créé des hiérarchies de contrôleur/vue incohérentes et a provoqué un blocage.
Fondamentalement, créez votre propre sous-classe UITableViewController et substituez loadView pour attribuer à self.view une vue différente et substituez la propriété tableView pour renvoyer une vue table séparée.
par exemple:
@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
Combinée à la solution de Keller, elle devient plus robuste, en ce sens que la tableView est désormais une vue normale, et non une vue racine de VC, et plus robuste face aux hiérarchies de vues changeantes. Exemple d'utilisation de cette façon:
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;
Il y a une autre utilisation possible pour cela:
Comme cette sous-classe sépare self.view de self.tableView, il est maintenant possible d’utiliser ce UITableViewController en tant que contrôleur normal et d’ajouter d’autres sous-vues à self.view sans les particularités de l’ajout de sous-vues à UITableView. affichez les contrôleurs directement dans une sous-classe de UITableViewController au lieu d’avoir des enfants UITableViewController.
Quelques points à surveiller:
Étant donné que nous ignorons la propriété tableView sans appeler super, il peut y avoir certaines choses à surveiller et à gérer si nécessaire. Par exemple, la définition de la table dans l'exemple ci-dessus n'ajoute pas la table à self.view et ne définit pas le cadre que vous souhaitez peut-être modifier. De plus, dans cette implémentation, aucune tableView par défaut ne vous est fournie lorsque la classe est instanciée, ce que vous pouvez également envisager d'ajouter. Je ne l'inclus pas ici parce que c'est au cas par cas, et cette solution correspond bien à la solution de Keller.