web-dev-qa-db-fra.com

UITableViewHeaderFooterView avec IB

Après de nombreuses années à éviter Interface Builder comme le fléau, j'ai décidé de lui donner une chance. Ce n'est pas facile.

Prenez UITableViewHeaderFooterView par exemple. Comme UITableViewCell, il a une propriété contentView. Contrairement à UITableViewCell, il n'y a pas de modèle dans la bibliothèque d'objets Interface Builder.

Comment sommes-nous censés utiliser Interface Builder pour créer une UITableViewHeaderFooterView avec le contenu contenu dans contentView? Le fait que registerNib:forHeaderFooterViewReuseIdentifier: existe me fait penser que cela devrait être possible.

24
hpique

C’est ce qui me rapproche le plus pour définir une UITableViewHeaderFooterView avec IB:

une. Créez une sous-classe UITableViewHeaderFooterView (MYTableViewHeaderFooterView).

b. Créez un fichier nib pour la contentView uniquement (MYTableViewHeaderFooterContentView).

c. Remplacez initWithReuseIdentifier: dans MYTableViewHeaderFooterView pour charger la vue définie dans le fichier nib.

 - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithReuseIdentifier:reuseIdentifier];
    if (self)
    {
        NSArray* objects = [[NSBundle mainBundle] loadNibNamed:@"MYTableViewHeaderFooterView"
                                                          owner:self
                                                        options:nil];
        UIView *nibView = [objects firstObject];
        UIView *contentView = self.contentView;
        CGSize contentViewSize = contentView.frame.size;
        nibView.frame = CGRectMake(0, 0, contentViewSize.width, contentViewSize.height);
        [contentView addSubview:nibView];
    }
    return self;
}

ré. Enregistrez la classe MYTableViewHeaderFooterView au lieu du fichier nib:

[self.tableView registerClass:[MYTableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"cell"];
30
hpique

Je viens de faire cela avec un pied de page et un fichier NIB:

  1. Créez un fichier NIB vide avec le nom CustomFooterView.xib .
  2. Editez le fichier NIB dans Interface Builder et modifiez la classe personnalisée UIView la plus élevée en UITableViewHeaderFooterView.
  3. Désactiver Mise en page automatique dans la carte NIB.
  4. Définissez la couleur d'arrière-plan de la vue UITableViewHeaderFooterView sur Par défaut .
  5. Rendre la vue libre et à la taille correcte (par exemple 320 x 44).
  6. Dans votre UITableViewController viewDidLoad, enregistrez le fichier NIB à utiliser avec un identifiant de réutilisation:

    [self.tableView registerNib:[UINib nibWithNibName:@"CustomFooterView" bundle:nil] forHeaderFooterViewReuseIdentifier:@"Footer"];
    
  7. Dans votre tableView:viewForFooterInSection: de UITableViewController, utilisez l'identifiant de pied de page pour récupérer et renvoyer la vue: 

    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
    {
        if (section == 2)
            return [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Footer"];
    
        return nil; 
    }
    
25
Markus Rautopuro

Il suffit d'utiliser le UITableViewCell modèle dans IB. Changer la classe en UITableViewHeaderFooterView. Ici vous l'avez ... avec un contentView.

13
Jean-Pierre

J'ai trouvé un moyen plus facile.

1) Créer une sous-classe de UITableViewCell et définir votre fichier xib

2) Dans votre fichier d'en-tête, changez la super-classe de UITableViewCell en UITableViewHeaderFooterView

C'est tout.

7
mdziadkowiec

Cette solution fonctionne bien, en particulier si vous souhaitez qu'elle fonctionne correctement par rapport aux guides de contenu lisible (introduits dans iOS 9). Au lieu de créer un UITableViewHeaderFooterView, il renvoie simplement un UIView personnalisé (à partir d'un XIB) lorsqu'il est requis:

  1. Créez une nouvelle classe qui sous-classe UIView ("AwesomeHeaderView") et créez vos points de vente:

    class AwesomeHeaderView: UIView {
        @IBOutlet var myCustomLabel: UILabel!
    }
    
  2. Créez un fichier XIB ("MyNewHeader.xib") avec un UIView en tant que La vue parent. Changez le type de classe du parent UIView en votre classe personnalisée nouvellement créée ("AwesomeHeaderView"). Si nécessaire, ajoutez des vues supplémentaires sous la forme d'enfants, des points de liaison, etc. (NB: pour vous assurer que les vues sont conformes aux nouveaux guides de contenu lisible, cochez les cases "Préserver les marges supérieures" et "Suivre la largeur lisible" sur tous les objets).
  3. Dans votre UIViewController (ou UITableViewController), appelez ce qui suit:

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        guard let headerView = NSBundle.mainBundle().loadNibNamed("MyNewHeader", owner: nil, options: nil).first as? AwesomeHeaderView else {
            return nil
        }
    
        // configure header as normal
        headerView.backgroundColor = UIColor.redColor()
        headerView.myCustomLabel.textColor = UIColor.whiteColor()
        headerView.myCustomLabel.text = "Hello"
    
        return header
    }
    
6
pheedsta

Les solutions de contournement suivantes me permettent de glisser-assigner des éléments IB au code en tant que variables. UITableViewHeaderFooterView n'autorise pas cela par défaut.

  1. créer un (Nouveau fichier/CocoaTouchClass) UITableViewHeaderFooterView . h.m.xib normalement

  2. temporairementrenommer la superclassede UITableViewHeaderFooterView en UIView. Glissez-attribuez vos éléments d'interface utilisateur au code selon vos besoins, IB affectera la valeur-clé .__ correctement, revenez à UITableViewHeaderFooterView lorsque vous avez terminé.

  3. dans votre table, utilisez registerNib: pour vous inscrire au lieu de registerClass:. prépare le reste de tableview normalement (c'est-à-dire: de la file d'attente). 
1
dklt

J'ai également rencontré l'avertissement de désapprobation ci-dessus et une incapacité à définir la couleur d'arrière-plan, etc. Finalement, j'ai constaté que, selon la documentation d'Apple,

Vous pouvez utiliser la classe [the UITableViewHeaderFooter] en l’état sans sous-classement dans la plupart des cas. Si vous avez un contenu personnalisé à afficher, créez les sous-vues pour votre contenu et ajoutez-les à la vue dans la propriété contentView. 

Suite à cette suggestion, j'ai pris les mesures suivantes:

  1. J'ai créé une xib avec une vue qui ne s'étend qu'à UIView - pas à UITableViewHeaderFooter. 
  2. Dans viewDidLoad, j'ai enregistré la classe UITableViewHeaderFooter intégrée.

    tableView.registerClass (UITableViewHeaderFooterView.self, pourHeaderFooterViewReuseIdentifier: "sectionHeader")

  3. Dans le délégué viewForHeaderInSection de mon UITableViewController, j'ai retiré la vue en-tête de cet identifiant et vérifié si cette vue contenait déjà une sous-vue. Sinon, je charge mon xib et l'ajoute. Ensuite, je règle mon texte au besoin.

    override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier("sectionHeader")!
    
    if header.contentView.subviews.count == 0 { header.contentView.addSubview(loadMyNib()) }
    
    let myView = header.contentView.subviews[0] as! MyView
    myView.label.text = "..."
    

Cela semble fonctionner, optimise la réutilisation et ne produit aucun avertissement.

_ { https://developer.Apple.com/library/prerelease/tvos/documentation/UIKit/Reference/UITableViewHeaderFooterView_class/index.html#//Apple_ref/occ/instm/UITableViewHeaderFooterView/prepareForReuse

1
xianwill

Je me suis dit que je devais créer une classe IBOutlet contentView dans votre classe headerFooter et la relier à votre "vue du contenu" dans la bibliothèque xib (placez votre xib comme une tableViewCell, View-> contentView-> mystuff).

Vous aurez des avertissements, ok prêt pour le hack ...

Supprimez l'IBOutlet et tout fonctionnera. 

0
BooRanger