web-dev-qa-db-fra.com

Comment ajouter un UIView au-dessus du UITableViewController actuel

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. 

53
user558096

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.

91
Daniel Saidi

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 :)

28
Thomas Verbeek

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];
11
Paco_777

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.

  1. donnez votre UITableViewController un identifiant StoryBoard i.e. MyStaticTableView
  2. créer une nouvelle sous-classe UIViewController et l'appeler UITableViewControllerContainer
  3. placez ce contrôleur à la place de votre UITableViewController à l'intérieur de votre storyboard
  4. ajoutez une sous-vue au nouveau contrôleur et reliez-la à une prise appelée " view_container "
  5. sur vous UITableViewControllerContainer viewDidLoad 

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:

  1. si vous avez un espace supplémentaire, assurez-vous d’ajouter le drapeau "veut le plein écran" à votre UITableViewController 
  2. s'il ne redimensionne pas correctement sur votre UITableViewControllerContainer

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

11
Nicola Ferruzzi

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];
6
Saikiran K

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.

6

L'exemple Apple "iPhoneCoreDataRecipes" utilise un NIB pour charger un en-tête sur un UITableView. Voir ici :

5
Olaf

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"]];
4
carmen_munich

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.

4

Swift 2018

Voici mon chemin avec le storyboard:

1) Ajouter une vue dans le storyboard.
 enter image description here

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)

4) Voilla!
 enter image description here

La vue ne défilera pas avec la vue tableau. Cela peut être facile à concevoir à partir du storyboard.

4
Nik Kov

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)
2
D. Sergeev

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.

1
Tomasz Kwolek

essayez: [self.view bringSubviewToFront:self.progView];

Ou vous pouvez essayer d'ajouter self.progView à la vue de votre table.

1
WrightsCS

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]
]];
1
cornr

Vous pouvez simplement mettre le code suivant dans viewDidAppear:

[self.tableView.superview addSubview:<your header view>];
1
Mig70

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];
0
Bob Spryn

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]; 
}
0
Salman Hasrat Khan

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)

    }

}
0
Brody Robertson

essayez quelque chose comme ça:

[self.tableView addSubview:overlayView];
overlayView.layer.zPosition = self.tableView.backgroundView.layer.zPosition + 1;
0
Filip Raj