J'ai des difficultés à ajouter une sous-vue (UIView) à partir de la méthode viewDidLoad d'un UITableViewController
Cela marche:
[self.view addSubview:self.progView];
Mais vous pouvez voir les lignes de cellules du tableau couler dans le progView UIView.
J'ai essayé cette approche:
[self.view.superview insertSubview:self.progView aboveSubview:self.view];
Ce qui est une tentative pour ajouter le progView, UIView à la vue d'ensemble, au-dessus de la vue actuelle. Quand j'essaye cela, UIView n'apparaît jamais.
-- METTRE À JOUR --
Voici la dernière tentative:
UIView *myProgView = (UIView *)self.progView; //progView is a method that returns a UIView
[self.tableView insertSubview:myProgView aboveSubview:self.tableView];
[self.tableView bringSubviewToFront:myProgView];
Le résultat est identique à [self.view addSubview: self.progView]; UIView apparaît mais semble être derrière la table.
J'ai essayé l'approche ci-dessus, mais je ne l'ai pas fait fonctionner. J'ai également constaté que cela nécessitait trop de configuration et de code, car cela impliquait de configurer la vue en tableau à partir de zéro (quelque chose qui se fait facilement à partir du storyboard).
Au lieu de cela, j'ai ajouté la vue que je voulais ajouter au-dessus de mon UITableView à la vue UINavigationController de UITableViewController, en tant que telle:
[self.navigationController.view addSubview:<view to add above the table view>];
Cette approche nécessite que vous ayez intégré UITableViewController dans un UINavigationController, mais même si vous ne souhaitez pas de contrôleur de navigation, vous pouvez toujours utiliser cette approche et masquer simplement la barre de navigation.
C'est en fait tout à fait possible et facile - cela nécessite juste un peu de recâblage. J'ai rencontré une situation similaire et codé pour me permettre d'ajouter des écrans de chargement au-dessus de mes vues de table. Cette approche vous permet également d'utiliser des cellules de tableau statiques avec votre propre contenu.
Si votre contrôleur est un UITableViewController dans un Storyboard ou un XIB et que vous souhaitez réaffecter self.view à un UIView standard tout en préservant votre vue de table existante:
Ajoutez ces variables d’instance à votre fichier d’en-tête:
IBOutlet UITableView *tableViewReference; // to keep a reference to the tableview
UIView *viewReference; // a reference to the new background view
Dans votre Storyboard ou fichier XIB: Connectez la tableView
dans la UITableViewController
à la variable tableViewReference
.
Puis dans votre fichier d'implémentation :
// Override the default accessors of the tableview and view
- (UITableView*)tableView { return tableViewReference; }
- (UIView*)view { return viewReference; }
- (void)viewDidLoad
{
[super viewDidLoad];
// instantiate the new self.view, similar to the tableview
viewReference = [[UIView alloc] initWithFrame:tableViewReference.frame];
[viewReference setBackgroundColor:tableViewReference.backgroundColor];
viewReference.autoresizingMask = tableViewReference.autoresizingMask;
// add it as a subview
[viewReference addSubview:tableViewReference];
/* remainder of viewDidLoad */
}
Bien que cela puisse paraître étrange, UITableViewController fait beaucoup de choses bizarres avec des références en coulisses. Vous devez attendre jusqu'à viewDidLoad pour pouvoir effectuer l'échange. Après ce point, les accesseurs pointeront sur les correctes UIView
et UITableView
.
Utilisation: Quelque chose comme
[self.view addSubview:myView];
ajoutera une UIView myView
devant la vue tabulaire, sans que myView
défile avec le contenu de la vue tabulaire.
Remarque: Cette réponse a été modifiée après avoir indiqué que la solution contenait un code limite paradoxal. UITableViewController fait des choses étranges avec les références qu'il contient. Des tests plus minutieux ont dérivé cette réponse plus simple :)
Vous pouvez augmenter la position z de la couche de votre vue.
Cela le fera afficher au-dessus des autres vues (qui ont une zPosition égale à 0, par défaut)
self.progView.layer.zPosition++;
[self.view addSubview:self.progView];
J'ai pu ajouter une sous-vue au-dessus d'un uitableviewcontroller en utilisant uiviewcontroller confinement.
UITableViewController est en fait très pratique pour les cellules statiques et c’est probablement le seul moment où la réponse commune "n’utilisez que la propriété uitableview" peut ne pas être viable.
Alors c'est comme ça que je le fais.
ajouter du code comme:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UITableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"MyStaticTableView"];
[self addChildViewController:vc];
[self.view_container addSubview:vc.view];
}
Problèmes que vous pouvez avoir:
ajouter le code:
- (void)viewWillAppear:(BOOL)animated
{
[[self.view_container.subviews lastObject] setFrame:self.view.frame];
}
à ce stade de votre UITableViewController, vous pouvez accéder directement à votre vue conteneur avec
self.view.superview.superview
et quoi que vous ajoutiez à cela sera montré sur votre contrôleur de vue de table
UITableViewController étant une sous-classe de UIViewController, vous devez ajouter la vue souhaitée à son aperçu.
Swift:
self.view.superview?.addSubview(viewTobeAdded)
Objective C:
[self.view.superview addSubview: viewTobeAdded];
Le problème est que la propriété view
de UITableViewController
est identique à la propriété tableView
. Cela signifie que la vue racine est always un contrôleur de vue de table et que tout ce qui est ajouté en tant que sous-vue est soumis à la fonctionnalité de vue de table. Cela a d'autres effets secondaires indésirables, tels que le défilement de vos sous-vues lorsque vous ne le souhaitez pas.
Il y a quelques options ici. Vous pouvez remplacer loadView
et installer vos propres vues et vues:
// note: untested
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
self.view.backgroundColor = [UIColor whiteColor];
UITableView *tblView = [[UITableView alloc]
initWithFrame:CGRectZero
style:UITableViewStylePlain
];
tblView.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight
;
self.tableView = tblView;
[self.view addSubview:tblView];
[tblView release];
}
Et ensuite, lorsque vous devez ajouter une sous-vue, ajoutez-la en dessous ou au-dessus de self.tableView
selon le cas.
Une autre option consiste simplement à créer une sous-classe UIViewController
qui répond à vos besoins. UITableViewController
honnêtement n’ajoute pas grand chose, et le peu de fonctionnalités qu’il implémente est facilement répliqué. Il existe des articles comme Recréer UITableViewController pour augmenter la réutilisation du code qui expliquent comment faire cela assez facilement.
L'exemple Apple "iPhoneCoreDataRecipes" utilise un NIB pour charger un en-tête sur un UITableView. Voir ici :
J'ai ajouté une image au dessus de la table. J'ai utilisé ce code:
self.tableView.tableHeaderView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"header.png"]];
J'ai eu un problème similaire et je l'ai résolu en utilisant le code ci-dessous:
[self.navigationController.view insertSubview:<subview>
belowSubview:self.navigationController.navigationBar];
Cela insère la vue au bon endroit en utilisant les contrôleurs présents dans Stack.
Voici mon chemin avec le storyboard:
1) Ajouter une vue dans le storyboard.
2) le lier avec la classe UITableViewController:
@IBOutlet weak var copyrightLabel: UILabel!
3) Ajoutez le dans le code
self.navigationController?.view.addSubview(copyrightView)
copyrightView.frame = CGRect(x: 0,
y: self.view.bounds.size.height - copyrightView.bounds.size.height,
width: self.view.bounds.size.width,
height: copyrightView.bounds.size.height)
La vue ne défilera pas avec la vue tableau. Cela peut être facile à concevoir à partir du storyboard.
Solution pour Swift (équivalent de Daniel Saidi):
Si votre contrôleur est un UITableViewController dans un Storyboard ou un XIB et que vous souhaitez réaffecter self.view à un UIView standard tout en préservant votre vue de table existante:
@IBOutlet var tableViewReference: UITableView!
var viewReference: UIView!
Puis dans votre fichier d'implémentation:
Ajoutez ces variables d'instance à votre fichier de contrôleur de vue de table:
override var tableView: UITableView! {
get { return tableViewReference }
set { super.tableView = newValue }
}
override var view: UIView! {
get { return viewReference }
set { super.view = newValue }
}
override func viewDidLoad() {
super.viewDidLoad()
self.edgesForExtendedLayout = UIRectEdge.None
self.extendedLayoutIncludesOpaqueBars = false
self.automaticallyAdjustsScrollViewInsets = false
//rewiring views due to add tableView as subview to superview
viewReference = UIView.init(frame: tableViewReference.frame)
viewReference.backgroundColor = tableViewReference.backgroundColor
viewReference.autoresizingMask = tableViewReference.autoresizingMask
viewReference.addSubview(tableViewReference)
}
Dans votre fichier Storyboard ou XIB: Connectez la tableView de UITableViewController à la variable tableViewReference.
Ensuite, vous pourrez ajouter des vues enfants comme suit:
self.view.addSubView(someView)
Pour conserver UIView au-dessus de la vue table dans UITableViewController, j'utilise une (ou plusieurs) des méthodes de délégation (UITableViewDelegate).
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.addSubview(headerView)
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
tableView.addSubview(overlayView) // adds view always on top
}
// if using footers in table view
tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) { ... }
Comme les avis ne peuvent avoir qu'un seul aperçu qui semble être une bonne solution, corrigez-moi si je me trompe. Toujours avoir 60 images par seconde, donc ça va pour moi.
essayez: [self.view bringSubviewToFront:self.progView];
Ou vous pouvez essayer d'ajouter self.progView
à la vue de votre table.
Mise à jour pour iOS 11:
Il est maintenant possible d'ajouter une sous-vue à UITableView
lors de l'utilisation de contraintes AutoLayout pour la zone sécurisée. Ces vues ne défileront pas le long de la table.
Cet exemple place une vue sous la barre de navigation au-dessus de la UITableView
d'une UITableViewController
[self.tableView addSubview:self.topBarView];
[NSLayoutConstraint activateConstraints:@[
[self.topBarView.topAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.topAnchor],
[self.topBarView.leadingAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.leadingAnchor],
[self.topBarView.trailingAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.trailingAnchor],
[self.topBarView.heightAnchor constraintEqualToConstant:40.0]
]];
Vous pouvez simplement mettre le code suivant dans viewDidAppear:
[self.tableView.superview addSubview:<your header view>];
Il peut y avoir des raisons pour ne pas le faire, mais cela fonctionne pour moi jusqu'à présent. Si vous utilisez un ap
Dans viewDidLayoutSubviews
, vous pouvez l'exécuter, mais assurez-vous de ne l'exécuter qu'une seule fois de façon évidente.
self.searchTableView = [[UITableView alloc] initWithFrame:self.tableView.frame style:UITableViewStylePlain];
self.searchTableView.backgroundColor = [UIColor purpleColor];
[self.view.superview addSubview:self.searchTableView];
J'ai eu un problème similaire où je voulais ajouter un indicateur de chargement sur mon UITableViewController. Pour résoudre ce problème, j'ai ajouté mon UIView en tant que sous-vue de la fenêtre. Cela a résolu le problème. Voici comment je l'ai fait.
-(void)viewDidLoad{
[super viewDidLoad];
//get the app delegate
XYAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
//define the position of the rect based on the screen bounds
CGRect loadingViewRect = CGRectMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2, 50, 50);
//create the custom view. The custom view is a property of the VIewController
self.loadingView = [[XYLoadingView alloc] initWithFrame:loadingViewRect];
//use the delegate's window object to add the custom view on top of the view controller
[delegate.window addSubview: loadingView];
}
Swift 4
Il s'agit de la version la plus simplifiée d'un certain nombre de réponses dans laquelle nous recomposons la hiérarchie des vues. Cette approche ne nécessite pas de sorties supplémentaires pour les storyboards/nibs et fonctionne également avec des instances construites par programme.
class MyTableViewController: UITableViewController {
var strongTableView: UITableView?
override var tableView: UITableView! {
get {
return strongTableView ?? super.tableView
}
set {
strongTableView = newValue
}
}
override func viewDidLoad() {
super.viewDidLoad()
// theoretically we could use self.tableView = self.tableView but compiler will not let us assign a property to itself
self.tableView = self.view as? UITableView
self.view = UIView(frame: self.tableView!.frame)
self.view.addSubview(tableView)
}
}
essayez quelque chose comme ça:
[self.tableView addSubview:overlayView];
overlayView.layer.zPosition = self.tableView.backgroundView.layer.zPosition + 1;