Decirle a un delegado personalizado cuándo llamar a un método

He creado una clase personalizada con varios métodos en y también agregué métodos de delegado a esa clase que se pueden llamar desde otra clase que importa mi clase personalizada. En particular estoy trabajando con iOS. Aquí hay una pequeña muestra de mis archivos de encabezado (.h) y de implementación (.m):

//iCloud.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@protocol iCloudDelegate;
@class iCloud;

@interface iCloud : NSObject {
    __weak id<iCloudDelegate> delegate_;
}

@property (nonatomic, weak) id <iCloudDelegate> delegate;

//Methods (abridged for StackOverflow)
+ (void)checkCloudAvailability;

@end

@class iCloud;
@protocol iCloudDelegate <NSObject>
//Methods (abridged for StackOverflow)
@optional
- (void)documentWasSaved;
@required
- (void)iCloudAvailable:(BOOL)status;
@end

Y parte de mi implementación (.m):

#import "iCloud.h"
@implementation iCloud
@synthesize delegate;

- (void)documentWasSaved {
    [[self delegate] documentWasSaved];
}

-(void)iCloudAvailable:(BOOL)status {
    [[self delegate] iCloudAvailable:status];
}

+ (void)checkCloudAvailability {
NSLog(@"Checking iCloud availablity...");
NSURL *returnedURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

if (returnedURL){
    NSLog(@"iCloud is available");
} else {
    NSLog(@"iCloud not available. ☹");
}
}

Revisé numerosos tutoriales, publicaciones SO, código de muestra y más para tratar de averiguar cómo decirle al delegado CUÁNDO llamar a los métodos de delegado, pero no he podido encontrar nada. La mayoría de las publicaciones muestran que la implementación debe agregar el delegado (usando el <DelegateName> sintaxis), sin embargo mi implementación de clase personalizada no es donde quiero usar el delegado (está en otra clase donde NO se crea el delegado).

Como puede ver en el código de ejemplo anterior, agregué los métodos de delegado (en la implementación), pero que yo sepa, todo esto hará que se llame a los métodos de delegado en las otras clases que lo usan. Si esto es correcto, ¿cómo hago para que el delegado llame a esos métodos (por ejemplo, desde mi checkCloudAvailability clase que no es uno de los métodos de delegado)? Aquí hay un ejemplo de lo que estoy tratando de hacer:

+ (void)checkCloudAvailability
    if (returnedURL){
      [[self delegate] iCloudAvailable:YES]; 
    ...
}

Cuando trato de usar el [[self delegate] methodName]; line me sale el siguiente error, y Xcode finge que ya no sabe de lo que estoy hablando: enter image description here

¿Por qué está pasando esto? ¿Por qué no puedo decirle al delegado cuando llamar a los métodos de delegado? Esto funciona bien dentro de los métodos delegados, pero ¿por qué no en la clase en la que se está implementando?

Se agradecerán pensamientos, ideas, enlaces, tutoriales, código o ayuda de cualquier tipo.

preguntado el 31 de diciembre de 12 a las 15:12

4 Respuestas

El error dice que no puede encontrar un método. delegate no está disponible en el contexto de un método de clase (es decir, uno denotado con un + señal). Esto puede parecer confuso, porque self dentro de un método de clase no corresponde a una instancia, sino a una clase; la propiedad delegate, por otro lado, pertenece a una instancia, lo que significa que no está disponible.

Para abordar esto, debe hacer checkCloudAvailability un método de instancia, o reescribirlo de la siguiente manera:

+(void)checkCloudAvailabilityWithDelegate:(id<iCloudDelegate>)delegate {
    ...
}

Respondido el 31 de diciembre de 12 a las 16:12

En el último caso, creo que sería más fácil si simplemente creara un método de clase checkCloudAvailability eso devolvería si iCloud está disponible o no. La delegación no es realmente necesaria en este caso. - Scott Berrevoets

@Scott Estoy de acuerdo: la única razón que veo para usar un delegate hay que mantener la coherencia con algo que tiene acceso a un delegate. Por ejemplo, si varios ejemplo métodos podrían potencialmente reutilizar este clase método, podrían compartir el código que verifica si el @optional El método se implementa pasando un delegado al método de clase. - Serguéi Kalinichenko

Sí, ambos tienen razón, esto podría ser mucho más simple, estoy de acuerdo. He usado sus comentarios aquí para cambiar mi patrón de diseño aquí y funciona maravillosamente. Además, tenga en cuenta que el método en la pregunta fue solo un ejemplo. - Sam Spencer

Llama clase método +(void)checkCloudAvailability. "self" en métodos de clase significa objeto de clase, no objeto de instancia. Pero delegue la variable declarada para el objeto de instancia.

Respondido el 31 de diciembre de 12 a las 16:12

Mira, es un método de clase. También usaré una propiedad en lugar de una variable de instancia:

@property (weak, nonatomic) id<iCloudDelegate> delegate;
@synthesize delegate = delegate_;

Respondido el 31 de diciembre de 12 a las 16:12

Cuando usa la anotación '+' antes de una llamada de función, se convierte en un método estático. Dentro de un método estático, no puede llamar a 'self'

Respondido el 31 de diciembre de 12 a las 16:12

Usted puede llamar al self, simplemente denota una cosa diferente (una clase, en lugar de una instancia). Creo que esta fue la fuente principal de la confusión del OP. - Serguéi Kalinichenko

Estás mezclando tu nomenclatura. Por un lado, un método de Objective-C no es lo mismo que una función, y no existe un método estático en Objective-C. Métodos con el prefijo + son métodos de clase, no métodos estáticos. - jlehr

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.