2010-12-27 11 views
14

Zawsze uważałem, że nie można zadeklarować właściwości obiektu w kategorii. Dopóki mój partner nie zrobił tego w kodzie naszej aplikacji i wydawało się, że działa.Od kiedy można zadeklarować właściwości Objective-C 2.0 w kategorii?

Poszedłem na upominek z SO i Google, aby wytłumaczyć mu, że nie, kategorie Celu-C mogą być używane tylko do dodawania metod, a nie właściwości. Znalazłem takie pytania jak:

Ale potem znalazłem this link na stronie Apple, który zawiera następujące informacje deklaracji @property:

Deklaracja właściwości zaczyna się od słowa kluczowego @property o wartości . @property może pojawiają się w dowolnym miejscu na liście deklaracji metody znajdującej się na interfejsie klasy . @property może pojawiają się również w deklaracji protokołu lub kategorii. (Podkreślenie dodane)

wiem, że to nie działa:

@interface MyClass() 
NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Ale to kompiluje:

@interface MyClass() 
@property NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Moje pytanie jest (a) Jaka jest najlepsza praktyka tutaj? i (b) czy jest to coś, co jest nowością w Objective-C 2.0, i zamiast używać "prawdziwego" iVar, po prostu używa pamięci asocjacyjnej za kulisami, aby to działało?

Odpowiedz

31

Zawsze można zadeklarować kategorię @property. To, czego nie możesz zrobić - i nadal nie możesz - deklaruje miejsce przechowywania dla właściwości w tej kategorii, ani jako zmienna instancji, ani przez `@synthesize.

Jednak ....

@interface MyClass() nie jest kategorii. Jest to rozszerzenie klasy i ma wyraźnie bardziej specyficzną rolę niż kategoria.

Mianowicie rozszerzenie klasy może być użyte do rozszerzenia interfejsu klasy @, a to obejmuje @ właściwości, które można @synthesized (w tym syntezowanie pamięci w nowoczesnym środowisku wykonawczym).

Foo.h: 

@interface Foo 
@end 

Foo.m: 

@interface Foo() 
@property int x; 
@end 

@implementation Foo 
@synthesize x; // synthesizes methods & storage 
@end 

po prostu wykorzystuje asocjacyjną przechowywanie za kulisami do tej pracy?

Nie - jest to prawdziwa zmienna instancji. Nowoczesne środowisko wykonawcze rozwiązuje delikatny problem klasy podstawowej.


@interface MyClass() 
NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Powyższe nie działa (zgodnie z oczekiwaniami), ponieważ foobar jest skuteczne, to zmienna globalna.

Jeśli go zmienić na:

@interface MyClass() { 
    NSInteger foobar; 
} 
- (void) someCategorizedMethod; 
@end 

Potem pracował z najnowszej wersji kompilatora LLVM (z prawem flagami, jak @Joshua wskazano w komentarzu).

+0

Aby dodać do tego, jego pierwszy przykład gdzie dodaje iVar jest całkowicie poprawny w llvm przy -Xclang -fobjc-nonfragile-abi2 –

+1

Byłoby, gdyby dodawał ivar. W takim przypadku dodaje on zmienną statyczną, która nie jest zmienną instancji. – bbum

+0

dziękuję za obszerne wyjaśnienie. Będę udostępniać ten link moim partnerom kodującym! – makdad

1

Ogólnie mówiąc, właściwości nie różnią się od innych metod. Dopóki używany ivar jest dostępny w klasie zwykłej, nie ma żadnego problemu. To tylko cukier syntaktyczny.

Rzeczy stają się coraz trudniejsze, jeśli również ivar jest tworzone automatycznie, jak to jest możliwe w konfiguracjach niektórych.

Najważniejsze jest to, że deklaracja ivar jest niezależna od własności.

1

Przechowywanie w celach rekrutacji jest rozwiązaniem. Zapoznaj się z tym post.

+0

Dzięki za kontynuację - jest to rzeczywiście możliwe rozwiązanie tego problemu. – makdad

Powiązane problemy