2009-11-10 20 views
40

Si creo un initWith personalizado para un objeto, ¿incluyo básicamente el código que agregaría si quisiera sobrescribir init?Agregar un initWith personalizado?

-(id) init { 
    self = [super init]; 
    if (self) { 
     NSLog(@"_init: %@", self); 
    } 
    return(self); 
} 

e.g.

-(id) initWithX:(int) inPosX andY:(int) inPosY { 
    self = [super init]; 
    if(self) { 
     NSLog(@"_init: %@", self); 
     posX = inPosX; 
     posY = inPosY; 
    } 
    return(self); 
} 

Gary

Respuesta

81

Puede crear un designado inicializador que acepte todos los parámetros que desea que estén disponibles en la inicialización.

Luego llama desde su otro -(id)init su inicializador designado con los parámetros adecuados.

Solo el inicializador designado inicializará la superclase [super init].

Ejemplo:

- (id)init 
{ 
    return [self initWithX:defaultX andY:defaultY]; 
} 

- (id)initWithPosition:(NSPoint)position 
{ 
    return [self initWithX:position.x andY:position.y]; 
} 


- (id)initWithX:(int)inPosX andY:(int)inPosY 
{ 
    self = [super init]; 
    if(self) { 
     NSLog(@"_init: %@", self); 
     posX = inPosX; 
     posY = inPosY; 
    } 
    return self; 
} 

El inicializador designado es -(id)initWithX:andY: y te llaman de otros inicializadores.

En caso de que quiera extender esta clase, llame a su inicializador designado desde la subclase.

+0

¿Cuál es el motivo del paréntesis entre 'self' para la línea' return (self); '? ¿Devuelve un valor 'BOOL'? – musubi

+0

'return (self)' fue un error tipográfico ... – stefanB

6

Sí, eso es exactamente cómo lo hago. Un ligero cambio cortará una línea de código:

if (self = [super init]) { 

A diferencia:

self = [super init]; 
if(self) { 
+2

GCC con advertencias habilitados se quejará , porque '=' en 'if' se usa más comúnmente por accidente que intencionalmente. Lo escribiría de la forma en que OP lo tiene ahora, pero para silenciar la advertencia, 'if ((self = [super init]))' lo hará. – ephemient

+0

por lo que le gustaría copiar el mismo código de inicialización a los 150 métodos de inicialización diferentes que tiene para esta clase realmente compleja? – stefanB

+0

No, Stefan, generalmente hago lo que haces.La forma en que leí su ejemplo fue cambiar init: a initWithX: yY :, en lugar de agregar initWithX: yY :, por lo que no entró en este aspecto. Pero es un gran punto, ¡me alegra que lo hayas hecho! Gracias, efímero, por el comentario. Siempre me he preguntado por qué los ejemplos de código a menudo lo hacen, ya que se construye bien sin él. Aparentemente en mi XCode nunca había recibido todas las advertencias habilitadas. ¡Me has inspirado! –

9

me gustaría sugerir la creación de un inicializador principal que maneja la mayor parte de la obra. Luego puede crear cualquier cantidad de otros inicializadores que todos llamen a este principal. La ventaja de esto es que si desea cambiar el proceso de inicialización, solo tendrá que cambiar un punto (en general). Podría verse así:

-(id) initWithX:(float)x { 
    if (self = [super init]) { 
     /* do most of initialization */ 
     self.xVal = x; 
    } 
    return(self); 
} 

-(id) init { 
    return [self initWithX:0.0f]; 
} 

En este ejemplo initWithX: es nuestro inicializador principal. El otro inicializador (init) simplemente llama a initWithX: con un valor predeterminado (en este caso 0).

+0

Su 'init' debe devolver el resultado de [self initWithX: 0.0f]. –

+0

Sí, lo extrañé. Fijo. Gracias. – dbachrach

2

A veces, desea volver a utilizar un código de inicialización y modificar el comportamiento solo ligeramente para los inicializadores específicos. En este caso, hago lo siguiente:


- (id) init 
{ 
    self = [super init]; 
    if (!self) return nil; 

    // These values are always initialised this way 
    ivar1 = 10; 
    ivar2 = @"HellO"; 
    ivar3 = [[NSMutableArray alloc] initWithCapacity:10]; 
    ivar4 = 22; 

    return self; 
} 

- (id) initWithIvar4:(int) aValue 
{ 
    // call -init on self, which will call -init on super for us, and set 
    // up ivar1, ivar2, ivar3, and ivar4. 
    self = [self init]; 
    if (!self) return nil; 

    // Change ivar4 from the default 22 to whatever aValue is. 
    ivar4 = aValue; 

    return self; 
} 

+0

Esa es otra opción, pero en caso de que llame solo a init, terminará con ivar4 no inicializado, y tendrá que recordar que en ese inicializador específico no lo hace inicialice algunas variables, pero otros inicializadores las inicializan ... suena demasiado propenso a errores ... – stefanB

+0

Disculpe, no proporcioné un ejemplo muy decente. Este código fue diseñado para aceptar que 'ivar4' tiene un valor predeterminado de 0, a menos que se establezca específicamente con' initWithIvar4: '. También podría establecer fácilmente 'ivar4' en' - [self init] 'también, pero tiene razón, podría terminar fácilmente con algunas variables inicializadas y otras no, y no ser capaz de rastrear fácilmente donde se establecen ciertas variables . – dreamlax

+0

Código editado para hacerlo más sensato. – dreamlax

4

Para modern Objective-C ...

UDFile.h

#import <Foundation/Foundation.h> 

@interface UDFile : NSObject 

@property (nonatomic, strong) NSString *name; 

- (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER; 

@end 

UDFile.m

#import "UDFile.h" 

@implementation UDFile 

- (instancetype)initWithName:(NSString *)name { 
    self = [super init]; 
    if (self) { 
     _name = [name copy]; 
    } 
    return self; 
} 

- (instancetype)init { 
    return [self initWithPathname:@""]; 
} 
Cuestiones relacionadas