2009-11-10 29 views
40

Jeśli utworzę niestandardowy initWith dla obiektu, czy zasadniczo dodaję kod, który chciałbym dodać, jeśli chcę zastąpić init?Dodawanie niestandardowego initWith?

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

np.

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

gary

Odpowiedz

81

Można utworzyć jeden inicjator oznaczony jako, który akceptuje wszystkie parametry, które mają być dostępne podczas inicjowania.

Następnie wywołasz ze swojego innego -(id)init wyznaczonego inicjalizatora z odpowiednimi parametrami.

Tylko wyznaczony inicjator zainicjuje super klasy [super init].

Przykład:

- (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; 
} 

Wyznaczony inicjująca jest -(id)initWithX:andY: i wywołać go od innych inicjalizatorów.

Jeśli chcesz przedłużyć tę klasę, wywołaj swój inicjator z podklasy.

+0

Jaki jest powód nawiasu wokół 'self' dla wiersza' return (self); '? Czy zwraca wartość 'BOOL'? – musubi

+0

'return (self)' było literówką ... – stefanB

6

Tak, to jest dokładnie jak to zrobić. Jedna drobna zmiana będzie wyciąć wiersz kodu:

if (self = [super init]) { 

W przeciwieństwie do:

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

GCC z włączonymi ostrzeżeniami będą narzekać , ponieważ '=' w 'if' jest częściej używane przez przypadek niż celowo. Napisałbym to tak, jak OP ma to teraz, ale żeby uciszyć ostrzeżenie, "if ((self = [super init]))" (zwróć uwagę na dodatkowe nawiasy). – ephemient

+0

, więc chcesz skopiować ten sam kod inicjujący do wszystkich 150 różnych metod inicjowania, które masz dla tej naprawdę skomplikowanej klasy? – stefanB

+0

Nie, stefan, ja na ogół robię to, co robisz.Sposób, w jaki przeczytałem jego przykład, polegał na zmianie init: na initWithX: iY :, zamiast dodawania initWithX: i Y :, więc nie wchodził w ten aspekt. Ale to świetny punkt, cieszę się, że to zrobiłeś! Dzięki, efhemient, za komentarz. Zawsze zastanawiałem się, dlaczego przykłady kodu często to robią, ponieważ bez tego wszystko w porządku. Najwyraźniej w moim XCode nie otrzymałem wszystkich ostrzeżeń. Zainspirowałeś mnie! –

9

Sugerowałbym tworząc jeden główny inicjator, który obsługuje większość prac. Następnie możesz utworzyć dowolną liczbę innych inicjalizatorów, które wszyscy nazywają tym głównym. Zaletą tego jest to, że jeśli chcesz zmienić proces inicjalizacji, będziesz musiał zmienić tylko jedno miejsce (ogólnie). Może wyglądać tak:

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

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

W tym przykładzie initWithX: jest naszym głównym inicjatorem. Inny inicjator (init) po prostu wywołuje initWithX: z wartością domyślną (w tym przypadku 0).

+0

Twój 'init' powinien zwrócić wynik [self initWithX: 0.0f]. –

+0

Tak, brakowało tego. Naprawiony. Dzięki. – dbachrach

2

Czasami należy ponownie użyć kodu inicjalizacyjnego i zmodyfikować tylko nieznacznie zachowanie dla określonych inicjatorów. W tym przypadku, należy wykonać następujące czynności:


- (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

To jest inna opcja, ale w przypadku, gdy wywołasz tylko init, skończysz z nie inicjalizacją ivar4 i będziesz musiał pamiętać, że w tym konkretnym inicjalizatorze nie masz zainicjować niektóre zmienne, ale inne inicjalizatory inicjują je ... brzmi trochę za bardzo błąd podatny na mnie ... – stefanB

+0

Niestety, nie dostarczyłem przyzwoitego przykładu. Kod ten został zaprojektowany, aby zaakceptować, że 'ivar4' ma wartość domyślną 0, chyba że jest ustawione specyficznie dla' initWithIvar4: '. Równie łatwo możesz ustawić 'ivar4' w' - [self init] ', ale masz rację, możesz łatwo skończyć z niektórymi zainicjowanymi zmiennymi, a niektóre nie, i niełatwo jest prześledzić, gdzie określone są pewne zmienne . – dreamlax

+0

Zmieniono kod, aby był bardziej sensowny. – dreamlax

4

Dla 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:@""]; 
} 
Powiązane problemy