Acceso al método estático de delegado en el problema de Objective-c

Tengo un extraño problema en el objective c. Aquí está el código:

STViewController.h

#import <UIKit/UIKit.h> @interface STViewController : UIViewController <UIAlertViewDelegate> +(void)myStaticMethod; @end 

STViewController.m

 #import "STViewController.h" @implementation STViewController - (void)viewDidLoad { [super viewDidLoad]; [STViewController myStaticMethod]; } + (void)myStaticMethod { UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Foo bar" message:@"baz bat" //what does self even mean in this context? The class object STViewController? delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; [alert show]; [alert release]; } #pragma mark UIAlertViewDelegate // TRICKY PART if it's static it works, if it's not, it doesn't. // even though the protocol declares instance methods (with a minus). + (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { NSLog(@"It works!"); } @end 

¿Por qué pasó esto? ¿Es esto correcto? No recibo errores ni advertencias. ¿Hace la opción – / + en la statement de methods de protocolo algo?

En primer lugar, debe saber que una Class (normalmente obtenida del object [MyClass class] ) también es un object ObjC válido. Esto significa que también puedes enviar un post a un object de class.

Por ejemplo

 @interface MyClass : NSObject + (NSString *)name; @end @implementation MyClass + (NSString *)name { return NSStringFromClass(self); // note in class method, self == [MyClass class] } @end // ------- in some method id cls = [MyClass class]; // the correct type should be Class, but since Class is an object, id will also work NSLog(@"%@", [cls name]); // call like instance method - MyClass NSLog(@"%@", [MyClass name]); // call like class method - MyClass 

por lo que puede usar su object de class como otro object y llamar al método de class como método de instancia.

¡Y los methods de class son en realidad methods de instancia! la diferencia es que los methods de class son methods de instancia de metaclass , que es la class de Class . Para más información sobre metaclass: http://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html


Además, la interfaz de su class es incorrecta, porque no es posible (al less en el momento del comstackdor) agregar un protocolo a una metaclass. así que si haces [self conformsToProtocol:@protocol(UIAlertViewDelegate)] devolverá NO. pero implementó + alertView:clickedButtonAtIndex: que agregará este método como el método de instancia de la metaclass, por lo que el código de delegado funciona y [self responseToSelector:@selector(alertView:clickedButtonAtIndex:)] devolverá SÍ.

En los methods de class self refiere al object de class. El object de class es un object objc normal (derivado de NSObject ) que recibirá los posts enviados a la class (methods de class, aquellos con el "+").

En su caso, utilizó el object de class como delegado de un UIAlertView (que funciona porque la API de UIAlertView no requiere explícitamente un object de id<UIAlertViewDelegate> tipo estático id<UIAlertViewDelegate> ). Ahora, la vista de alerta simplemente enviará sus posts de delegado al object de class, que de nuevo está bien, ya que los implementó como methods de class.

Está configurando self como delegado de alerta que es dynamic, pero la llamada de método que es estática, por lo que está mal, en primer lugar, porque cuando llamará a + (void)myStaticMethod algún time en un futuro self podría no ser inicializado y ser nil . Por eso, pueden aparecer otros errores, así como un comportamiento indefinido.