iphone - pantalla - notificaciones instagram ios 11
Delegados vs. Notificaciones en iPhoneOS (7)
Intento llamar a un método en mi controlador de vista raíz desde un controlador de vista hijo de modo que cuando cambie mis opciones actualicen automáticamente la vista raíz, que a su vez actualizará muchos otros controladores de vista. Para la segunda parte he usado notificaciones, pero para esta primera estoy tratando de usar un delegado porque (así me han hecho creer) es una buena práctica de programación. Tengo problemas para hacerlo funcionar y sé que puedo configurar otra notificación fácilmente para hacer el trabajo. ¿Debo seguir intentando implementar el delegado o simplemente usar una notificación?
¿Es realmente necesario que su controlador de vista raíz conozca los cambios, o solo las subvistas?
Si el controlador raíz no tiene que saberlo, enviar las configuraciones para que envíen las notificaciones que están buscando las otras parece ser una mejor respuesta para mí, ya que simplifica el código. No es necesario introducir más complejidad de la que debe.
Delegar es una buena práctica de programación para muchas situaciones, pero eso no significa que deba usarla si no se siente cómodo con ella. Tanto la delegación como las notificaciones ayudan a desacoplar los controladores de vista entre sí, lo cual es algo bueno. Las notificaciones pueden ser un poco más fáciles de codificar y ofrecen la ventaja de que varios objetos pueden observar una notificación. Con los delegados, tal cosa no se puede hacer sin modificar el objeto delegante (y es inusual).
Algunas ventajas de delegar:
- La conexión entre delegar objeto y delegado se hace más clara, especialmente si la implementación del delegado es obligatoria.
- Si se debe pasar más de un tipo de mensaje de delegado a delegado, la delegación puede aclarar esto al especificar un método de delegado por mensaje.
Para las notificaciones, puede usar múltiples nombres de notificación, pero todas las notificaciones terminan en el mismo método del lado del observador (posiblemente requiera una desagradable instrucción de cambio).
Solo tú puedes decidir qué patrón es más apropiado para ti. En cualquier caso, debería considerar no hacer que su controlador de vista envíe la notificación o el mensaje de delegado. En muchos casos, el controlador de vista debe cambiar el modelo y luego el modelo debe informar a sus observadores o su delegado que se ha cambiado.
Implementar un patrón de delegado es simple:
En su ChildViewController.h, declare el protocolo de delegado que el delegado debe implementar más adelante:
@protocol ChildViewControllerDelegate <NSObject> @optional - (void)viewControllerDidChange:(ChildViewController *)controller; @end
En la parte superior del archivo, crea una variable de instancia para mantener el puntero al delegado en tu ChildViewController:
@protocol ChildViewControllerDelegate; @interface ChildViewController : UIViewController { id <ChildViewControllerDelegate> delegate; ... } @property (assign) id <ChildViewControllerDelegate> delegate; ... @end
En RootViewController.h, haga que su clase se ajuste al protocolo delegado:
@interface RootViewController : UIViewController <ChildViewControllerDelegate> { ...
En la implementación de RootViewController, implemente el método de delegado. Además, cuando crea la instancia de ChildViewController, debe asignar el delegado.
@implement RootViewController ... // in some method: ChildViewController *controller = [[ChildViewController alloc] initWithNibName:... controller.delegate = self; ... - (void)viewControllerDidChange:(ChildViewController *)controller { NSLog(@"Delegate method was called."); } ...
En la implementación de ChildViewController, llame al método de delegado en el momento apropiado:
@implementation ChildViewController ... // in some method: if ([self.delegate respondsToSelector:@selector(viewControllerDidChange:)]) { [self.delegate viewControllerDidChange:self]; } ...
Eso es. (Nota: he escrito esto de memoria, así que probablemente haya algunos errores tipográficos).
En este caso, no necesita usar ninguna delegación o notificación porque realmente no necesita comunicarse directamente entre sus vistas. Como dijo gerry3, debe cambiar el modelo de datos en sí mismo y luego dejar que todas las demás vistas respondan a ese cambio.
Su modelo de datos debe ser un objeto independiente al que todos los controladores de vista tengan acceso. (La manera perezosa es estacionarlo como un atributo del delegado de la aplicación.) Cuando el usuario realiza un cambio en la Vista A, el controlador de la Vista A escribe que cambia al modelo de datos. Luego, cada vez que se abren las Vistas B a la Z, los controladores leen el modelo de datos y configuran las vistas de manera apropiada.
De esta forma, ni los puntos de vista ni sus controladores deben conocerse entre sí y todos los cambios ocurren en un objeto central para que sean fácilmente rastreados.
Las notificaciones pueden hacer que el comportamiento en el tiempo de ejecución de su programa sea mucho más complejo. Piense en ello como un goto con múltiples destinos. El orden de esos destinos no está definido. Si alguna vez falla, hay poca información de seguimiento de la pila.
Hay casos en los que tiene sentido usar notificaciones, la típica es comunicar un cambio de modelo o un cambio de estado global a sus vistas. Ejemplo, la red está inactiva, la aplicación va a renunciar, etc.
Vale la pena aprender el patrón delegado en iOS. Los delegados le dan rastros de pila completos cuando depura. Resultan en un comportamiento de tiempo de ejecución significativamente más simple al mismo tiempo que logran el objetivo de desacoplar sus objetos.
Los delegados son un poco difíciles de acostumbrar, pero creo que es la mejor práctica y, como Apple, simplemente funcionan .
Siempre uso la declaración de protocolo formal. Es un poco más lógico en mi mente, y está muy claro en el código. Sugiero usar un UIView para cambiar tus opciones en lugar de un controlador. Siempre uso un controlador principal y tengo muchas UIViews subclasificadas que el único controlador puede controlar. (Sin embargo, puede modificar el siguiente código para un controlador, si realmente necesita un controlador en lugar de una vista normal ) . En el archivo de encabezado de la vista secundaria, haga que se vea así:
// ChildView.h
#import <UIKit/UIKit.h>
@protocol ChildViewDelegate; // tells the compiler that there will be a protocol definition later
@interface ChildViewController : UIView {
id <ChildViewDelegate> delegate;
// more stuff
}
// properties and class/instance methods
@end
@protocol ChildViewDelegate // this is the formal definition
- (void)childView:(ChildView *)c willDismissWithButtonIndex:(NSInteger)i; // change the part after (ChildView *)c to reflect the chosen options
@end
El método entre @protocol
y el segundo @end
se puede llamar en algún lugar de la implementación de ChildView, y luego su controlador de vista raíz puede ser el delegado que recibe la ''notificación''.
El archivo .m debería ser así:
// ChildView.m
#import "ChildView.h"
@implementation ChildView
- (id)initWithDelegate:(id<ChildViewDelegate>)del { // make this whatever you want
if (self = [super initWithFrame:CGRect(0, 0, 50, 50)]) { // if frame is a parameter for the init method, you can make that here, your choice
delegate = del; // this defines what class listens to the ''notification''
}
return self;
}
// other methods
// example: a method that will remove the subview
- (void)dismiss {
// tell the delegate (listener) that you''re about to dismiss this view
[delegate childView:self willDismissWithButtonIndex:3];
[self removeFromSuperView];
}
@end
Luego, el archivo .h del controlador de vista raíz incluiría el siguiente código:
// RootViewController.h
#import "ChildView.h"
@interface RootViewController : UIViewController <ChildViewDelegate> {
// stuff
}
// stuff
@end
Y el archivo de implementación implementará el método definido en el protocolo en ChildView.h, porque se ejecutará cuando ChildView llame para que se ejecute. En ese método, coloca las cosas que suceden cuando recibes la notificación.
Me gustaría agregar:
los objetos que reciben notificaciones pueden reaccionar solo después de que haya ocurrido el evento. Esta es una diferencia significativa de la delegación. El delegado tiene la oportunidad de rechazar o modificar la operación propuesta por el objeto delegante. Observar objetos, por otro lado, no puede afectar directamente una operación inminente.
Por lo general, si necesita actualizar la interfaz de usuario según un cambio en los datos de un modelo, los controladores de vista observarán los datos relevantes del modelo y actualizarán sus vistas cuando se notifiquen los cambios.
Veo la delegación como un poco más formal y como la distinción que Peter Hosey compartió recientemente:
La diferencia es que la delegación es para comunicación uno (y bidireccional), mientras que las notificaciones son para muchas, comunicación unidireccional.
Además, he encontrado que (completamente) actualizando la vista en viewWillAppear:
funciona bien (pero esta no es la mejor solución cuando el rendimiento es una preocupación).