ios viewdidappear

ios - ¿Cómo hacer algunas cosas en viewDidAppear solo una vez?



(7)

Quiero verificar la mesa de trabajo y mostrar una alerta si contiene valores específicos cuando aparece la vista. Puedo colocar el código en viewDidLoad para asegurarme de que solo se invoca una vez, pero el problema es que la vista de alerta se muestra demasiado rápido. Sé que puedo configurar un temporizador para diferir la apariencia de la alerta, pero creo que no es una buena solución.

Revisé la pregunta iOS 7 - Diferencia entre viewDidLoad y viewDidAppear y encontré que hay un paso para verificar si existe la vista. Así que me pregunto si hay alguna API para hacer esto?

Actualización: "solo una vez" significa la vida útil de la instancia del controlador de vista .


Esta solución llamará a viewDidAppear solo una vez a lo largo del ciclo de vida de la aplicación, incluso si creas el objeto múltiple del controlador de vista, no se llamará después de una vez. Por favor, consulte la respuesta de Rmaddy arriba

Puede realizar el selector en viewDidLoad o puede usar dispatch_once_t en viewDidAppear . Si encuentra una solución mejor, por favor comparta conmigo. Así es como hago las cosas.

- (void)viewDidLoad { [super viewDidLoad]; [self performSelector:@selector(myMethod) withObject:nil afterDelay:2.0]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; static dispatch_once_t once; dispatch_once(&once, ^{ //your stuff [self myMethod]; }); }


Al leer otros comentarios (y en base a la respuesta de @rmaddy), sé que esto no es lo que solicitó OP, sino para aquellos que vienen aquí por el título de la pregunta:

extension UIViewController { var isPresentingForFirstTime: Bool { return isBeingPresented() || isMovingToParentViewController() } }

ACTUALIZAR

Debe usar este método en viewDidAppear y viewWillAppear . (Gracias a @rmaddy)

ACTUALIZACIÓN 2

Este método solo funciona con controladores de vista presentados de manera modesta y controladores de vista empujados. no está funcionando con un childViewController. usar didMoveToParentViewController sería mejor con childViewControllers.


Existe un método estándar incorporado que puede utilizar para esto.

C objetivo:

- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if ([self isBeingPresented] || [self isMovingToParentViewController]) { // Perform an action that will only be done once } }

Swift 3:

override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if self.isBeingPresented || self.isMovingToParentViewController { // Perform an action that will only be done once } }

La llamada a isBeingPresented es verdadera cuando un controlador de vista se muestra por primera vez como resultado de que se muestra de manera modesta. isMovingToParentViewController es verdadero cuando un controlador de vista se empuja por primera vez en la pila de navegación. Uno de los dos será verdadero la primera vez que aparezca el controlador de vista.

No es necesario tratar con ivars BOOL o cualquier otro truco para rastrear la primera llamada.


Intente establecer un valor BOOL, cuando ocurra la situación, llámelo.

@interface AViewController : UIViewController @property(nonatomic) BOOL doSomeStuff; @end @implementation AViewController - (void) viewWillAppear:(BOOL)animated { if(doSomeStuff) { [self doSomeStuff]; doSomeStuff = NO; } }

en algún lugar usted inicia instancia AViewController:

AddEventViewController *ad = [AddEventViewController new]; ad.doSomeStuff = YES;

¿No estás seguro de por qué haces esto en ViewDidAppear ? Pero si desea que doSomeStuff sea privado y se soSomeStuff llamado a soSomeStuff solo una vez, aquí hay otra solución mediante notificación:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomeStuff) name:@"do_some_stuff" object:nil]; - (void) doSomeStuff {}

Luego publica cuando en algún lugar:

[[NSNotificationCenter defaultCenter] postNotificationName:@"do_some_stuff" object:nil];


Las respuestas de rmaddy son realmente buenas, pero no resuelven el problema cuando el controlador de vista es el controlador de vista raíz de un controlador de navegación y todos los demás contenedores que no pasan estas banderas a su controlador de vista secundario.

De modo que en esas situaciones encuentro mejor usar una bandera y consumirla más adelante.

@interface SomeViewController() { BOOL isfirstAppeareanceExecutionDone; } @end @implementation SomeViewController -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if(isfirstAppeareanceExecutionDone == NO) { // Do your stuff isfirstAppeareanceExecutionDone = YES; } } @end


Puedes usar esta función en el método ViewDidLoad.

performSelector: withObject: afterDelay:

Llamará a esa función después de la demora. para que no tenga que usar ningún objeto temporizador personalizado. y por una vez puedes usar

Dispatch_once DCD block.Just performSelector en el dispatch_once block llamará a performSelector solo una vez cuando se llama a ViewDidLoad

Espero eso ayude


Si entiendo su pregunta correctamente, simplemente puede configurar una variable BOOL para reconocer que viewDidAppear ya se ha llamado, por ejemplo:

- (void)viewDidAppear { if (!self.viewHasBeenSet) { // <-- BOOL default value equals NO // Perform whatever code you''d like to perform // the first time viewDidAppear is called self.viewHasBeenSet = YES; } }