web-dev-qa-db-fra.com

Impossible de définir le cadre correctement avant viewDidAppear

Je me demandais si quelqu'un savait pourquoi, lorsque vous définissez le cadre d'une sous-vue dans viewDidLoad et viewWillAppear, les modifications ne prennent pas effet à l'écran, mais si vous les définissez dans viewDidAppear, elles le sont?

Dans mon cas, je charge un xib personnalisé avec deux vues de table, puis j'essaie de les décaler dans viewDidLoad pour laisser de la place pour une autre vue qui est ajoutée dans viewDidLoad car il n'est pas toujours nécessaire de l'afficher.

Le problème, c’est que lorsque j’ai mis le cadre dans viewDidLoad ou viewWillAppear il est défini sur l’objet, je peux le voir en l’imprimant, mais cela ne se reflète pas à l’écran. Si je déplace mes appels de cadre vers viewDidAppear, tout fonctionnera comme prévu.

Est-il faux de penser que je devrais être capable de définir le cadre dans viewDidLoad?

- (id)init {
    if ( self = [super initWithNibName:@"MyView" bundle:nil] ) {}

    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.descriptionWebView = [[[UIWebView alloc] initWithFrame:CGRectMake( 0, 0, self.view.frame.size.width, 200 )] autorelease];

    [self.view addSubview:self.descriptionWebView];

    self.tableView1.autoresizingMask = UIViewAutoresizingNone;
    self.tableView2.autoresizingMask = UIViewAutoresizingNone;

    [self.descriptionWebView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"...." withExtension:@"html"]]];

    table1LocationWithHeader = CGRectMake( self.tableView1.frame.Origin.x, 200, self.tableView1.frame.size.width, self.tableView1.frame.size.height - 200 );
    table2LocationWithHeader = CGRectMake( self.tableView2.frame.Origin.x, 200, self.tableView2.frame.size.width, self.tableView2.frame.size.height - 200 );

    //this will NOT work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    //this will NOT work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}


- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    //this WILL work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}


//I added these after comments for stack overflow users, it seems like viewDidLayoutSubviews is the best place to set the frame

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    //this will NOT work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    //this WILL work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}
39
nacross

viewDidLoad est appelé lorsque la classe est chargée. Toutefois, aucun élément ui n'a été initialisé. Toute tentative de les référencer sera écrasée ou indisponible lors du processus d'initialisation entre les appels viewDidLoad et viewDidAppear. Une fois que tous les éléments ui ont été initialisés et dessinés, viewDidAppear est appelé.

viewDidLoad - Appelé après le chargement en mémoire de la vue du contrôleur

À ce stade, la vue ne fait pas partie de la hiérarchie.

viewWillAppear - Indique au contrôleur de vue que sa vue est sur le point d'être ajoutée à une hiérarchie de vues.

Encore une fois, la vue doit encore être ajoutée à la hiérarchie des vues. 

viewDidAppear - Indique au contrôleur de vue que sa vue a été ajoutée à une hiérarchie de vues.

Ce n'est qu'alors que la vue est ajoutée à la hiérarchie des vues.

Mettre à jour

La viewDidLayoutSubviews est l'endroit le plus approprié pour modifier l'interface avant qu'elle n'apparaisse réellement à l'écran.

viewDidLayoutSubviews - Indique au contrôleur de vue que sa vue vient de présenter ses sous-vues.

94
Leon Storey

Voir ce fil Quand layoutSubviews est-il appelé?
Lorsque vous utilisez autolayout, la structure n’appelle pas automatiquement layoutSubviews. C'est très important. De ref:

  • init ne provoque pas l’appel de layoutSubviews (duh)
  • addSubview: appelle layoutSubviews dans la vue ajoutée, la vue à laquelle il est ajouté (vue cible) et toutes les sous-vues de la cible. ...


Si vous ajoutez une sous-vue dans viewDidLoad, layoutSubviews a été appelé avant viewDidAppear et vous pouvez obtenir la taille correcte des sous-vues. Mais si vous ne faites rien, layoutSubviews sera appelé après viewDidAppear. C'est à votre code.

2
BollMose

in viewWillAppear () 

il suffit d'appeler une fois layoutIfNeeded () pour la vue dont vous voulez obtenir le cadre.

si tableView alors tableView.layoutIfNeeded () par exemple

0
Mohshin Shah