Método de llamada en el controlador de vista actual desde el delegado de la aplicación en iOS

Tengo dos controladores de vista (BuildingsViewController y RoomsViewController) que usan una función dentro del delegado de la aplicación llamada carga. La función de carga básicamente hace una solicitud HTTP, y si tiene éxito o no, desencadena una vista previa. Esto está funcionando bien.

La parte con la que estoy luchando es desde el método connectionDidFinishLoading del delegado de la aplicación. Necesito poder actualizar básicamente el controlador de vista actual a través del método viewWillAppear de ese controlador de vista. Dentro de la función viewWillAppear de cada controlador de vista, tengo un código que determina los botones en la barra de herramientas inferior.

Quiero que el botón “subir” en la barra de herramientas de cada controlador de vista se elimine automáticamente cuando la carga se realiza a través del delegado de la aplicación.

Intenté hacer [viewController viewWillAppear:YES] desde el método connectionDidFinishLoading del delegado de la aplicación, pero nunca se llama.

Espero ser lo suficientemente claro. Cualquier ayuda es muy apreciada.

Gracias.

Para hacer la actualización de la vista, no llame a viewWillAppear si la vista ya se muestra. Lo que quieres hacer es lo siguiente:

Cuando el método ConnectionDidFinishLoading se desencadena publicar una notificación

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

En su viewController observe esta notificación. Lo haces al agregar este código a tu método init o viewDidLoad

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshView:) name:@"refreshView" object:nil]; 

Ahora implemente -(void)refreshView:(NSNotification *) notification método de -(void)refreshView:(NSNotification *) notification en su viewController para administrar su vista a su gusto.

Si se dirige a iOS 4.0 y posterior, puede usar la propiedad rootViewController la ventana para obtener el controlador de vista actual.

 [window.rootViewController viewWillAppear]; 

Si desea que su aplicación se ejecute en versiones anteriores a iOS 4.0, puede agregar una variable de instancia al delegado de la aplicación para recordar qué controlador de vista llamó al método de upload , haciendo que el controlador se envíe a sí mismo como parámetro.

 - (void)upload:(UIViewController *)viewController { self.uploadingViewController = viewController; // This is the property you add ... } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self.uploadingViewController viewWillAppear]; self.uploadingViewController = nil; } 

También debería considerar usar un método diferente para volver a cargar los botones, algo así como reloadButtons , ya que no está relacionado con la vista que aparece en este caso. Luego llamaría a ese método desde viewWillAppear .

Paso 1:

En el archivo .h de tu delegado de aplicaciones, debes declarar un protocolo como este:

 @protocol AppConnectionDelegate  @required -(void)connectionFinished:(NSObject*)outObject; @end 

En el mismo archivo, agregue un ivar como ese:

 id *delegate; 

Declara el ivar como una propiedad:

 @property (nonatomic, assign) id delegate; 

En el archivo Delegado .m de la aplicación, sintetice el ivar:

 @synthesize delegate; 

En el archivo .m de la aplicación Delegado, en connectionDidFinishLoading, haga lo siguiente:

 if([self.delegate respondsToSelector:@selector(connectionFinished:)]) { [self.delegate connectionFinished:objectYouWantToSend]; } 

En el archivo .h de su viewcontroller, implemente AppConnectionDelegate importando una referencia al archivo delegado de la aplicación:

 #import "AppDelegate_iPhone.h" //if using iPhone #import "AppDelegate_iPad.h" //if using iPad 

En el mismo archivo, al final de la primera línea de la statement de interfaz, haga lo siguiente:

 @interface AppDelegate_iPhone : AppDelegate_Shared  

Declarar ivars en consecuencia:

 AppDelegate_iPhone *appDelegate; //if using iPhone AppDelegate_iPad *appDelegate; // if using iPad 

En el archivo .m de viewcontroller en viewDidLoad (), obtenga una referencia al delegado de su aplicación usando:

Si iPhone;

 appDelegate = (AppDelegate_iPhone*)[[UIApplication sharedApplication] delegate]; 

Si iPad:

 appDelegate = (AppDelegate_iPad*)[[UIApplication sharedApplication] delegate]; 

Luego configure el viewcontroller para que sea el delegado en viewDidLoad () haciendo:

 appDelegate.delegate = self; 

Ahora solo necesita implementar el método connectionFinished en el archivo .m:

 - (void)connectionFinished:(NSObject*)incomingObject { //Do whatever you want here when the connection is finished. IncomingObject is the object that the app delegate sent. } 

Ahora, cuando se invoca connectionDidFinishLoading de su delegado de aplicación, se notificará al controlador de vista.

[Es una práctica recomendada configurar appDelegate.delegate = nil si ha terminado de usar la conexión de callback finalizada]

Esto es probado y probado. Si tienes preguntas, deja un comentario ……

–EDITAR–
Esta es una alternativa robusta a NSNotification. Yo uso ambos dependiendo de los requisitos. El proceso que uso para decidir entre usar NSNotification o una callback de delegado usando un protocolo es simplemente:

Para notificaciones:
Un emisor, múltiples oyentes.
No hay referencia posible entre el emisor y el oyente.
No es necesario enviar objetos complejos / múltiples

Para callbacks de delegates usando protocolos:
Un remitente, limitado (por lo general 1) oyentes.
Una referencia entre el emisor y el oyente es posible.
Se deben enviar objetos complejos / múltiples (por ejemplo, objetos de respuesta que deben enviarse)

Sé que enviar objetos es posible a través de notificaciones, pero prefiero los protocolos para eso.
–EDITAR–

Lo peor de todo es que puede hacer que ambos controladores de vista se adhieran a un protocolo de método simple que eliminará ese botón y actualizará la vista. Luego, en su método connectionDidFinishLoading, ya que sabe que su controlador de vista debe cumplir con ese protocolo, por su diseño, simplemente haga algo como

 ViewController curView = (Get the current view controller somehow); [curview refreshView];