webentwicklung-frage-antwort-db.com.de

UIViewController viewWillAppear wird beim Hinzufügen als SubView nicht aufgerufen

Ich habe eine UIViewController, die ich aus einem anderen View-Controller heraus lade und dann deren Ansicht zu einer UIScrollView hinzufüge.

self.statisticsController = [self.storyboard instantiateViewControllerWithIdentifier:@"StatisticsViewController"];
self.statisticsController.match = self.match;

[self.scrollView addSubview:self.statisticsController.view];

Ich habe Haltepunkte in den Controller für die Statistikansicht gesetzt und viewDidLoad wird aufgerufen, viewWillAppear jedoch nicht.

Liegt es daran, dass ich es nicht in die Hierarchie schiebe oder so?

20
Fogmeister

Sie sollten statisticsController als untergeordneten Ansichtscontroller des Controllers hinzufügen, zu dessen Ansicht Sie ihn hinzufügen.

self.statisticsController = [self.storyboard instantiateViewControllerWithIdentifier:@"StatisticsViewController"];
self.statisticsController.match = self.match;

[self.scrollView addSubview:self.statisticsController.view];
[self addChildViewController:self.statisticsController];
[self.statisticsController didMoveToParentViewController:self];

Ich bin nicht sicher, ob viewDidAppear aufgerufen wird, aber Sie können didMoveToParentViewController: im untergeordneten Controller überschreiben, und das wird aufgerufen. Sie können also jeden Code eingeben, den Sie in viewDidAppear eingegeben hätten.

43
rdelmar

Ich stoße -viewWillAppear: nicht erneut auf ein Problem Nach dem googeln bin ich hierher gekommen. Ich habe einige Tests durchgeführt und herausgefunden, dass die Aufrufreihenfolge von -addSubview und -addChildViewController: wichtig ist.

Fall 1. löst -viewWillAppear: des Controllers aus, aber Fall 2, es WON'T rufen -viewWillAppear: auf.

Fall 1:

  controller?.willMoveToParentViewController(self)

  // Call addSubview first
  self.scrollView.addSubview(controller!.view)
  self.addChildViewController(controller!)

  controller!.didMoveToParentViewController(self)

Fall 2:

  controller?.willMoveToParentViewController(self)

  // Call adChildViewController first      
  self.addChildViewController(controller!)      
  self.scrollView.addSubview(controller!.view)

  controller!.didMoveToParentViewController(self)
36
AechoLiu

Standardmäßig werden Erscheinungsrückrufe automatisch an untergeordnete Elemente weitergeleitet .. __, die mit der shouldAutomaticallyForwardAppearanceMethods - Eigenschaft festgelegt werden. Überprüfen Sie den Wert dieser Eigenschaft. Wenn es NO ist und Ihr untergeordneter viewController beim Erscheinungsbild des Containers richtig angezeigt werden soll, sollten Sie child mit den folgenden Methoden in der Controller-Lebenszyklus-Implementierung des Containers benachrichtigen:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    for (UIViewController *child in self.childViewControllers) {
        [child beginAppearanceTransition:YES animated:animated];
    }
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.child endAppearanceTransition];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    for (UIViewController *child in self.childViewControllers) {
        [child beginAppearanceTransition:NO animated:animated];
    }
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self.child endAppearanceTransition];
}

Anpassen des Aussehens und des Rotationsrückrufverhaltens

Mein Problem behoben Ich hoffe es wäre hilfreich. 

16

Wie in einer anderen Antwort erwähnt, ruft der übergeordnete View-Controller möglicherweise nicht viewWillAppear usw. auf, wenn shouldAutomaticallyForwardAppearanceMethods auf false eingestellt ist. UINavigationController und UITabBarController sind dafür bekannt. In diesem Fall müssen Sie beginAppearanceTransition(_ isAppearing: Bool, animated: Bool) im untergeordneten View-Controller aufrufen, wobei isAppearing auf true gesetzt ist, wenn die Ansicht angezeigt wird, und umgekehrt.

Sie müssen diese Anrufe an geeigneten Stellen in Ihrem Code durchführen, normalerweise, wenn Sie Ihren untergeordneten View-Controller hinzufügen und entfernen.

Vergessen Sie nicht, endAppearanceTransition in Ihrem untergeordneten Ansichtscontroller aufzurufen, wenn der benutzerdefinierte Übergang beendet ist. Andernfalls werden viewDidAppear und viewDidDisappear nicht aufgerufen.

4
bompf

Pro Apple ( https://developer.Apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html ) lautet die korrekte Reihenfolge der API-Aufrufe zum Hinzufügen eines untergeordneten View-Controllers:

[self addChildViewController:childVC];
[self.view addSubview:childVC.view];
[childVC didMoveToParentViewController:self];

Ich hatte aber immer noch das Problem, dass viewWillAppear beim Kind VC nicht immer wieder aufgerufen wurde. Mein Problem war, dass es eine Race-Bedingung gab, die dazu führen konnte, dass der Code oben ausgeführt wurde , bevor viewDidAppear in der Containeransicht aufgerufen wurde. Durch die Sicherstellung, dass viewDidAppear bereits aufgerufen wurde (oder die Hinzufügung des Kindes VC erst verschoben wurde), wurde es für mich gelöst.

2
gumbypp

Die vorherigen Antworten sind richtig, aber wenn es jemandem hilft - wenn Sie loadView im untergeordneten View-Controller überschreiben, wird keine der anderen UIViewController-Methoden aufgerufen.

Ich brauchte einige Zeit, um zu verstehen, warum mein Code nicht richtig lief, bis ich merkte, dass ich versehentlich loadView anstelle von viewDidLoad überschrieben hatte.

1
Liron

In meinem Fall habe ich festgestellt, dass eine viewWillAppear:-Methode in meiner UINavigationController-Klasse falsch geschrieben wurde:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // other stuff
}

Beachten Sie, dass ich anstelle von super.viewWillAppear(animated)super.viewWillDisappear(animated) geschrieben habe.

Dies führte dazu, dass alle UIViewControllers, die sich in dieser UINavigationController befanden, die viewWillAppear:-Methode nicht aufgerufen haben.

Hoffe das hilft jemandem bei einem ähnlichen Problem.

0