2013-10-27 12 views
7

Mam klasę A, która eksponuje sposób pobierania i ustawiania obiektu typu Foo. W żargonie własności, to zazwyczaj zadeklarować to w interfejsie:Jak mogę zadeklarować wartość @, ale uniemożliwić jej utworzenie ivar?

@property (nonatomic, strong) Foo * foo; 

to (w nowoczesnych ObjC) wytwarza zarówno dostępowych i sieci AN ivar, _foo do przechowywania.

Jeśli chcę wykonać niestandardową pracę w akcesoriach, mogę samodzielnie wykonać jedną lub obie z nich. Ale co, jeśli nie chcę tylko wykonywać niestandardową pracę, w rzeczywistości nie chcę, aby ivar? Innymi słowy, robię coś innego z obiektem Foo, jak przekazywanie go tam iz powrotem do innego wewnętrznego obiektu, z którym jestem skomponowany. Nie muszę w ogóle przechowywać pamięci dla foo w instancji A.

Wydaje się, że mam dwie możliwości:

  1. zadeklarować właściwości, wdrożyć zarówno akcesorów i po prostu zignorować faktu, że kompilator tworzy przechowywania _foo i nigdy go używać.
  2. Zadeklaruj wyraźnie moje akcesory: - (Foo *)foo i - (void)setFoo:(Foo *)foo w interfejsie, tak jak kiedyś w przedmodernistycznym ObjC.

Pierwszy wydaje się nieelegancki w czasie wykonywania, a drugi wydaje się nieelegancki w deklaracji (gdzie prawdopodobnie miałbym teraz mieszankę właściwości i właściwościopodobnych akcesorów).

Czy istnieje sposób, aby zadeklarować nieruchomość i czy ma ona służyć wyłącznie jako deklaracja?

Odpowiedz

4

Jeśli zastąpić zarówno setter i getter i nie używać zmiennej w ustawieniu i pobierającym zmienna nie zostanie utworzona.

Na przykład, jeśli masz klasę, dla której chcesz właściwość firstName i lastName, ale być może także setter i getter dla nieruchomości fullName, jeśli fullName seter prostu analizuje ciąg do firstName i lastName i ustawia te właściwości do tego (i nigdy nie przechowuje pełnego łańcucha do zmiennej fullName), a twój fullName pobiera po prostu returns połączony firstName + lastName i nigdy nie używa zmiennej fullName, nigdy nie zostanie utworzony.

Jest to zgodne z oficjalną dokumentacją Apple. Scroll down to "You Can Implement Custom Accessor Methods"

+0

Masz rację! Dzięki za wskaźnik doktora, tęskniłem za tym. Uważam, że to zachowanie jest trochę magiczne jak na mój gust, ale cieszę się, że o tym wiem. –

+0

Jak można zauważyć w dokumentacji, możesz zadeklarować właściwość jako 'readonly' lub' writeonly' i nadpisać tylko ten akcesor i uniknąć utworzenia zmiennej. – nhgrif

9

Użyj słowa kluczowego @dynamic w pliku implementacji. Zwykła dyskusja pod numerem @dynamic opisuje, że nie tworzy ona w czasie kompilacji użytkowników. Zazwyczaj nie wspomina się, że jest to również nie robi nic, aby utworzyć pamięć masową dla właściwości, co jest dokładnie tym, co jest pożądane w tym przypadku.

@implementation A 
@dynamic foo; 

- (Foo *)foo 
{ 
    // get a Foo from somewhere and return it. 
} 

- (void)setFoo:(Foo *)foo 
{ 
    // do something with foo 
} 

@end 

(Uwaga:. Odpowiedział na moje własne pytanie, od kiedy odkryliśmy to podczas zapisywania się na pytanie i wydawało się interesujące a nonobvious)

+0

+1 '@ dynamic' jest jednym z moich ulubionych rzeczy więcej. –

2

@dynamic to prawdopodobnie droga.

Jednak istnieją dwa inne sposoby, można to zrobić również:

  1. Niezaimplementowane Kategoria

    Można użyć un realizowany kategorię do deklarowania właściwości, ale nie uzyskać poparcia przechowywanie:

    @interface Foo : NSObject 
    @end 
    
    @interface Foo (UnimplementedProperties) 
    @property (strong) id bar; 
    @end 
    
    @implementation Foo 
    @end 
    

    By nie deklarując realizację kategorii (@implementation Foo (UnimplementedProperties)), właściwości nie będzie syntetyzowany.

  2. Protokół

    Można zadeklarować właściwości na protokole, a następnie dokonać klasa zgodne z tym protokołem. Ma to ten sam efekt co niezaimplementowana kategoria: metody są zadeklarowane, ale właściwości nie są syntezowane.

    @protocol FooProperties <NSObject> 
    @property (strong) id bar; 
    @end 
    
    @interface Foo : NSObject <FooProperties> 
    
    @end 
    
+0

Świetne punkty, dzięki. Wadą tego jest to, że konsumenci obiektu widzą to rozróżnienie w nagłówku, ale nie powinien to być żaden interes moich rozmówców, jak zarządzam nieruchomością, o ile zachowuję się racjonalnie z ich punktu widzenia. –

+0

@BenZotto zgodził się, dlatego prawdopodobnie powinieneś użyć '@ dynamic'. Ale te podejścia mają również swoje zastosowania. :) –

+0

Yup, i nie przyszło mi do głowy, że te wzory mają skutek uboczny robienia tego, o co prosiłem. Dzięki. (W każdym razie, okazuje się, że obaj staramy się zbyt mocno, zobacz odpowiedź @ nhgrifa.) –

Powiązane problemy