2009-08-20 12 views
6

Chcę zwolnić kod, gdy właściwość jest dostępna i zmieniona. Używam @property i @synthesize w moim kodzie dla moich ivars. Właściwości są zachowane, więc chciałbym zachować te funkcje zarządzania pamięcią automatycznie generowane przez @synthesize.Jak zapewnić dodatkowe niestandardowe wdrożenie metod dostępu podczas używania @synthesize?

Jednak zakładam, że @synthesize mówi kompilatorowi, aby wygenerował kod metod dostępu bezpośrednio pod adresem @synthesize is, więc większość przypadków znajduje się na górze kodu, prawda?

A kiedy mam właściwość foo, otrzymuję metody -setFoo i -foo. Czy mogę po prostu zrobić taką metodę, aby wykonać jakiś niestandardowy kod po zmianie właściwości?

-(void)setFoo { 
    // custom stuff 
} 

Teraz to jest problem. Jak wykonać pierwszy? Nie chciałbym mieć tutaj innego imienia. Czy istnieje sposób na to, aby dyrektywa @synthesize utworzyła inne nazwy dla metod getter i setter, które następnie łatwo wywołuję? I nadal będę mógł używać składni dot, aby uzyskać do nich dostęp?

Odpowiedz

5

Możesz używać @property i @synthesize, tak jak zwykle, ale zapewnisz niestandardowy seter lub getter (lub oba), a te zostaną użyte. Zazwyczaj zrobię coś takiego:

// Override the setter 
- (void)setName:(NSString *)aName 
{ 
    if (name == aName) 
     return; 

    [name release]; 
    name = [aName retain]; 

    //custom code here 
} 

Kiedy używam właściwości set, wywoła ona moją metodę niestandardową. Jednak wynik będzie nadal syntetyzowany.

+1

FYI, Twój program ustawiający przykład ma błąd, ponieważ dwukrotne wywoływanie tego samego obiektu może spowodować zwolnienie tego obiektu przed jego zachowaniem. Nie jest to naprawdę wielka sprawa, ale pokazuje, jak trudne może być uzyskanie tych rzeczy dokładnie. –

+0

Nie jestem pewien, czy podążam, czy mógłbyś wyjaśnić, jak to powinno być napisane (nie jest tak, że nie wierzę ci, chciałbym wiedzieć, jak to zrobić właściwie). Dzięki :) – jbrennan

+1

Och, nvm Widzę problem, zaktualizuję go, aby odzwierciedlić zmiany. – jbrennan

1

Jeśli wprowadzisz implementację dla ustawiających lub pobierających, użyje jej zamiast wygenerowanej implementacji. Nie jest trudno wdrożyć "zachowujący" aspekt modułów pobierających i ustawiających, które są generowane przez kompilator podczas syntezy, więc możesz po prostu napisać własne moduły pobierające i ustawiające, które chciałbym powiedzieć i przejść z tym.

-2

Tak, w deklaracji @property można określić metody pobierające i ustawiające.

@property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo; 

W swoim foo i setFoo: metod, zadzwoń [self privateGetFoo] lub [self privateSetFoo:f] następnie kod niestandardowy.

Obiekt może również ustawić samego obserwatora za pomocą addObserver:forKeyPath:options:context:.

To powiedziawszy, nie sądzę, że którykolwiek z nich to bardzo czysty sposób robienia rzeczy. Lepiej napisać własny zdobywca/seter, jak sugerowali inni.

+0

Powiedziałeś: "W swoim foo i setFoo: methods ..." Podczas gdy dostępne są opcje [obj setFoo: x] i [obj foo], należy pamiętać, że ze względu na zmodyfikowaną właściwość, obj.foo nie będzie być dostępnym do pisania, a będziesz musiał użyć obj.setFoo = x. Nie jest to sposób, w jaki normalnie to robi @property, gdzie obj.foo jest używany zarówno do czytania, jak i pisania. – mahboudz

+0

Następnie object.foo jest równoważne [object privateFoo], który pokonuje cały cel używania właściwości. –

0

Jednym zwariowanym rozwiązaniem jest stworzenie abstrakcyjnej super klasy, która zapewnia normalną syntezę właściwości. Następnie utwórz konkretną podklasę, której faktycznie użyjesz, i która po prostu implementuje i zastępuje metodę (ta sama sygnatura) i wywołuje funkcję super, aby wykonać rzeczywiste ustawienie. Umożliwia to robienie wszystkiego, co chcesz zrobić przed lub po wywołaniu wdrożenia super.

Przykład:

@interface ALTOClassA : NSObject 


@property NSString *catName; 

@end 

Nic innego potrzebne w .m poza plikiem zgaszone dla tego testu.

Utwórz podklasę, nic nie potrzeba specjalnie w @interface

#import "ALTOClassA.h" 

@interface ALTOClassAJunior : ALTOClassA 

@end 

W @implementation robimy nasz nadpisanie.

#import "ALTOClassAJunior.h" 

@implementation ALTOClassAJunior 


- (void)setCatName:(NSString*)aCatName { 
    NSLog(@"%@",NSStringFromSelector(_cmd)); 
    [super setCatName:aCatName]; 
    NSLog(@"after super: self.catName %@", self.catName); 
} 
@end 

W użyciu:

ALTOClassAJunior *aCAJ = [ALTOClassAJunior new]; 
NSLog(@"aCAS.catName %@", aCAJ.catName); 

NSLog(@"set it to George."); 

[aCAJ setCatName:@"George"]; 

NSLog(@"aCAS.catName %@", aCAJ.catName); 

Pozwala to wykorzystać kod wygenerowany automatycznie i nadal robić rzeczy, które chcesz zrobić z klasą. Streszczenie Super Klasa jest często przydatnym rozwiązaniem dla wielu rzeczy.

Powiązane problemy