¿Cómo obtengo la subclass para inicializar la propiedad como su class correcta?

Tengo una class llamada SPPanelManager , que tiene una propiedad de otra class, denominada SPPanelSettingsManager . SPPanelManager tiene lo siguiente en su método -init :

 self.settingsManager = [[SPPanelSettingsManager alloc] init]; 

El propósito de SPPanelManager debe ser subclasificado, y las subclasss se utilizan en toda mi aplicación. Por ejemplo, hay SPGreetingManager . En el file .h de SPGreetingManager , he declarado:

 @property (nonatomic, strong) SPGreetingSettingsManager *settingsManager; 

que hace que el settingsManager sea de la class correcta. El problema es que cuando se inicializa la subclass SPGreetingManager , llama al método init anterior e inicializa el settingsManager como la class SPPanelSettingsManager , en lugar de SPGreetingSettingsManager .

¿Cómo puedo hacer que esto se inicialice como la class correcta para esa propiedad sin tener que volver a escribir el código de inicio en cada subclass?

La SPPanelManager ( SPPanelManager ) de alguna manera tiene que saber qué class quiere que el administrador del panel concreto use como settingsManager .

Apple usa el siguiente enfoque para combinar CALayers con UIViews:

La class base declara un método de class que devuelve la subclass concreta SPPanelSettingsManager :

 // in SPPanelManager.h + (Class)settingsManagerClass; 

… qué subclasss anulan para devolver su class personalizada:

 // in SPGreetingManager.m + (Class)settingsManagerClass { return [SPGreetingSettingsManager class]; } 

Ahora la superclass puede crear una instancia del administrador de configuration de la siguiente manera:

 self.settingsManager = [[[[self class] settingsManagerClass] alloc] init]; 

Otra solución común es usar una convención de nomenclatura. Solo coinciden los nombres de las classs: SPGreetingManager tiene un SPGreetingSettingsManager .

Por definición, cada … Manager debe tener un ajuste … ConfigurationManager.

 // in SPPanelManager.m init NSString *className = NSStringFromClass([self class]); className = [className stringByReplacingOccurrencesOfString:@"Manager" withString:@"SettingsManager"]; Class settingsManagerClass = NSClassFromString(className); NSAssert(settingsManagerClass != Nil, @"no settings manager class found"); self.settingsManager = [[[settingsManagerClass settingsManagerClass] alloc] init]; 

La ventaja es que las subclasss no tienen que anular un método común para declarar el tipo de class. Por otro lado, puede parecer un poco ofuscado lo que está sucediendo.

Además, el código anterior fuerza una relación de uno a uno entre las classs. No se puede reutilizar ningún controller de configuration.

¿Es SPPanelManager una class que desarrolló? Simplemente dale un init con un parámetro para la instancia de configuration.