web-dev-qa-db-fra.com

Pourquoi UIViewController s'étend-il sous UINavigationBar, contrairement à UITableViewController?

J'ai UITabbarController avec UINavigationController. J'ai une sous-classe de UIView que j'assigne comme view de UIViewController dans le navController. C'est assez standard, non? Voici comment je le fais

_productCategoryView = [[ProductCategoryView alloc] initWithFrame:self.view.frame];
self.view = _productCategoryView;

Ce view a un UITableView comme subView

_productCategoryTableView = [[UITableView alloc] initWithFrame:self.frame style:UITableViewStylePlain];
_productCategoryTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_productCategoryTableView.backgroundColor = [UIColor clearColor];
[self addSubview:_productCategoryTableView];

Par souci de débogage, je configure self.backgroundColor = [UIColor blueColor] Sur la vue.

À partir de l'initialisation ci-dessus de tableView, on pourrait penser que les vues frame de la vue et de la table sont identiques. Cependant, lorsque je lance dans iOS 7, L'origine de la vue est définie derrière le UINavigationBar. Cela est compréhensible car je mets self.navigationBar.translucent = YES; Dans ma sous-classe de UINavigationController. Mais ce que je ne comprends pas, c'est pourquoi la table est assise juste en dessous du navBar? Cela ne devrait-il pas aussi commencer par (0, 0), Qui se trouve derrière le navBar? Voir la capture d'écran Scenario 1 Ci-dessous. Remarquez la teinte bleue derrière navBar

Scenario 1

Maintenant, j’ai Push un autre viewController sur la pile de navigation, simplement en utilisant [self.navigationController pushViewController.....]. Encore une fois j'ai une coutume UIView avec un tableView dedans. Cependant, j'ai aussi un UILabel au-dessus de cette table et, encore une fois, pour le débogage, je lui ai donné un redColor. Cette fois-ci, je mets le Origin du label presque identique à celui de la vue.

CGRect boundsInset = UIEdgeInsetsInsetRect(self.bounds, UIEdgeInsetsMake(10, 10, 10, 10));

CGSize textSize = [_titleLabel.text sizeWithFont:_titleLabel.font
                               constrainedToSize:CGSizeMake(boundsInset.size.width, MAXFLOAT)
                                   lineBreakMode:NSLineBreakByWordWrapping];
printSize(textSize);
_titleLabel.frame = CGRectMake(boundsInset.Origin.x,
                               boundsInset.Origin.y,
                               boundsInset.size.width,
                               textSize.height);

Donc, suivant la logique ci-dessus, l'étiquette devrait être visible, non? Mais cette fois ce n'est pas le cas. Cette fois, l'étiquette est derrière le navBar.

Scenario - 2

Remarquez, la teinte rouge derrière la barre de navigation.

Je voudrais vraiment aligner la sous-vue sous la barre de navigation de manière cohérente. Mes questions sont

1. How is the tableView offset by 64pixels (height of nav + status bar in iOS 7) automatically, even though it's frame is same as the view's?

2. Why does that not happen in the second view?

61
unspokenblabber

Par défaut, les vues de UITableViewController sont automatiquement insérées dans iOS7 afin qu'elles ne commencent pas sous la barre de navigation/barre d'état. Il s’agit du contrôleur par le paramètre "Ajuster les encarts de la vue de défilement" de l’onglet Inspecteur d’attributs de UITableViewController dans Interface Builder, ou par le paramètre setAutomaticallyAdjustsScrollViewInsets: méthode de UIViewController.

Pour le contenu d'un contrôleur UIViewController, si vous ne souhaitez pas que le contenu de sa vue s'étende sous les barres supérieure/inférieure, vous pouvez utiliser les paramètres Étendre les bords sous les barres supérieures/Sous les barres inférieures dans Interface Builder. Ceci est accessible via la propriété edgesForExtendedLayout.

136
Greg

Objectif c:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.edgesForExtendedLayout = UIRectEdgeNone;
 }

Swift 2:

self.edgesForExtendedLayout = UIRectEdge.None

Swift 3+:

self.edgesForExtendedLayout = []
112
Gank

La réponse de @ Gank est correcte, mais le meilleur endroit pour le faire est sur le UINavigationControllerDelegate (si vous en avez un):

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
    viewController.edgesForExtendedLayout = UIRectEdge.None
}
10
Dan Rosenstark