Vuelva a cargar y no vuelva a cargar si presiona hacia atrás desde diferentes controlleres de vista. Rápido

Las tres primeras respuestas pueden resolver mis preguntas. Es difícil elegir cuál es el mejor. Entonces, escojo al que es el primero en responder mi pregunta. Perdón por aficionado e iOS Entusiasta. Gracias por tu ayuda. Lo aprecio.

introduzca la descripción de la imagen aquí

ViewController 1 tiene una vista de tabla.

Mi pregunta es cómo volver a cargar la vista de tabla solo si hago clic en volver desde el controller de vista 2 y no vuelvo a cargar la vista de la tabla si hago clic de nuevo desde la vista del controller 3.

En este momento, mi código para el button Atrás es

@IBAction func backButtonTapped(sender: AnyObject) { self.dismissViewControllerAnimated(true, completion: nil) } 

En el controller de vista 1. Sé que la vista de tabla se volverá a cargar desde el controller de vista 2 o 3

 override func viewDidAppear(animated: Bool) { loadTable() } 

Traté de poner loadTable () en viewDidLoad e intentar escribir el código siguiente para el button Atrás en el controller de vista 2. Pero, no funciona.

 let storyboard = UIStoryboard(name: "Main", bundle: nil) let controller = storyboard.instantiateViewControllerWithIdentifier("UserHomePageViewController") as! UserHomePageViewController controller.viewDidLoad() 

¿Alguna sugerencia de lo que debo hacer? Gracias por tu ayuda.

EDITAR:

Creo que esta es una forma más fácil de hacerlo, pero todavía no funciona como pensaba. Supongo que es porque el viewDidAppear se ejecuta antes de la llamada de reloadTableBool. ¿Correcto? Hay alguna manera de arreglarlo? Gracias. Tu ayuda sería apreciada.

 class 2ViewController @IBAction func backButtonTapped(sender: AnyObject) { let storyboard = UIStoryboard(name: "Main", bundle: nil) let controller = storyboard.instantiateViewControllerWithIdentifier("1ViewController") as! 1ViewController print("viewcontroller2 before call: \(controller.reloadTableBool)") controller.reloadTableBool = false print("viewcontroller2 after call: \(controller.reloadTableBool)") self.dismissViewControllerAnimated(true, completion: nil) } class 1ViewController var reloadTableBool = true override func viewDidAppear(animated: Bool) { print("viewcontroller1: \(reloadTableBool)") if reloadTableBool == true { loadTable() } } 

Cuando hago clic en volver a ver el controller 2, imprime

 viewcontroller2 before call: true viewcontroller2 after call: false viewcontroller1: true 

Si la visualización de vc2 la realiza vc1 y siempre está segura de invalidar los datos en vc1, puede hacer lo siguiente:

  • agregar una variable de instancia needsReload boolean a vc1
  • configúrelo en verdadero cada vez que visualice vc2 (y cuando instale vc1, por ejemplo, en awakeFromNib si procede de un storyboard)
  • solo realice el contenido de loadTable si needsReload es verdadero (tal vez refactorice esta lógica en loadTableIfNeeded )
  • no olvide establecer needsReload a false al final de loadTableIfNeeded

Este patrón de invalidation se encuentra en todo UIKit, vea, por ejemplo, UIView setNeedsLayout / layoutIfNeeded . La ventaja es que incluso si varios events hacen que los datos se invaliden, solo se actualizarán cuando lo necesite.

En su situación, tiene la ventaja adicional de mantener la lógica contenida en vc1 y no crear un acoplamiento innecesario entre sus VC, lo cual siempre es bueno.

— ACTUALIZACIÓN: implementación de muestra (ObjC pero obtendrá la idea)

Solo necesita manejar esto en VC1, olvídese de todo el contenido del button Atrás en VC2. Esta implementación marcará VC1 para recargar tan pronto como se presente VC2, pero de hecho recargará solo en viewWillAppear, cuando VC2 se descarta.

— ACTUALIZACIÓN 2: se agregó una recarga condicional basada en una callback delegada

Tenga en count que _needsReload ahora está configurado en la callback de delegado, no cuando se presenta VC2 por primera vez. En su lugar, configuramos VC1 como delegado de VC2. (la lógica _needsReload es realmente innecesaria al usar este método, manteniéndola como reference)

 //VC2: add a delegate to the interface @class VC2; @protocol VC2Delegate - (void) viewController:(VC2*)myVC2 didFinishEditingWithChanges:(BOOL)hasChanges; @end @interface VC2 @property (nonatomic, weak) id<VC2Delegate> delegate @end @implementation VC2 - (IBAction) finishWithChanges { [self.delegate viewController:self didFinishEditingWithChanges:YES]; } - (IBAction) finishWithoutChanges { [self.delegate viewController:self didFinishEditingWithChanges:NO]; } @end //VC1: implement the VC2Delegate protocol @interface VC1 () <VC2Delegate> @end @implementation VC1 { BOOL _needsReload } - (void) awakeFromNib { //adding this for completeness but the way you did it in Swift (at init) is correct [super awakeFromNib]; _needsReload = YES; } - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self reloadTableIfNeeded]; } - (IBAction) displayVC2 { VC2* myVC2 = ... //instanciate your VC2 here myVC2.delegate = self; //set as the delegate of VC2 [self presentViewController:myVC2 animated:YES completion:nil]; } - (void) viewController:(VC2*)myVC2 didFinishEditingWithChanges:(BOOL)hasChanges { _needsReload = hasChanges; [self reloadTableIfNeeded]; } - (void) reloadTableIfNeeded { if (_needsReload) { [self.tableView reloadData]; _needsReload = NO; } } @end 

Aquí hay un enlace a una pregunta que respondí hace un par de días. Use el delegado del controller de navigation para manejar el button Atrás. En su segundo controller de vista, configure el delegado en sí mismo y vuelva a cargar la vista de tabla cuando presione el button Atrás.

 override func viewDidLoad() { super.viewDidLoad() navigationController?.delegate = self } func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) { if let controller = viewController as? FirstViewController { controller.tableView.reloadData() } } 

NOTA: Estoy asumiendo que está utilizando el button Atrás del controller de navigation aquí.

EDITAR: Otro ejemplo con el button de volver a agregar manualmente:

 @IBAction func backButtonTapped(sender: AnyObject) { if let viewControllers = app.window?.rootViewController?.childViewControllers { viewControllers.forEach { ($0 as? FirstViewController)?.tableView.reloadData() } } self.dismissViewControllerAnimated(true, completion: nil) } 

Al ver como estás usando un controller de navigation:

 @IBAction func backButtonTapped(sender: AnyObject) { navigationController?.viewControllers.forEach { ($0 as? FirstViewController)?.tableView.reloadData() } self.dismissViewControllerAnimated(true, completion: nil) } 

Puede usar el enfoque de notifications fácilmente para esto.

Agregue el observador en su 1st ViewController en el método viewDidLoad.

 NSNotificationCenter.defaultCenter().addObserver(self, selector: "reloadTable:", name: "reloadTable", object: nil) func reloadTable(notification : NSNotification){ let isReload : NSNumber = notification.userInfo!["isReload"] as! NSNumber if (isReload.boolValue) { self.tableView.reloadData() } } 

Luego, publique una notificación como esta desde su 2nd y 3rd ViewController respectivamente cuando llame a dismissViewController.

 // From 2nd viewcontroller NSNotificationCenter.defaultCenter().postNotificationName("reloadTable", object: nil, userInfo: ["isReload" : NSNumber(bool: false)]) // From 3rd viewcontroller NSNotificationCenter.defaultCenter().postNotificationName("reloadTable", object: nil, userInfo: ["isReload" : NSNumber(bool: true)])