Jaka jest różnica między Ivars a właściwościami w Objective-C

Jaka jest semantyczna różnica między tymi 3 sposobami używania ivarów a właściwościami w objective-c?

1.

@class MyOtherObject; 
@interface MyObject {
}
@property (nonatomic, retain) MyOtherObject *otherObj;

2.

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}
    @property (nonatomic, retain) MyOtherObject *otherObj;

3.

    #import "MyOtherObject.h"
    @interface MyObject {
        MyOtherObject *otherObj;
    }
Author: Michael Currie, 2010-11-13

2 answers

Liczba 1 różni się od dwóch pozostałych tym, że forward deklaruje klasę MyOtherObject, aby zminimalizować ilość kodu widzianego przez kompilator i linker, a także potencjalnie uniknąć odniesień okrągłych. Jeśli zrobisz to w ten sposób pamiętaj, aby umieścić # import do .plik M.

Deklarując właściwość@, (i dopasowując @synthesize wm) plik, automatycznie generujesz metody accessora z semantyką pamięci obsługiwaną w sposób określony przez Ciebie. Regułą dla większości obiektów jest zachowanie, ale NSStrings, na przykład powinien używać Copy. Natomiast Singletoni i delegaci powinni zwykle używać przypisania. Akcesoria do pisania ręcznego są żmudne i podatne na błędy, więc oszczędza to wiele pisania i głupich błędów.

Również deklaracja właściwości syntetyzowanej pozwala wywołać metodę accessor używając notacji kropkowej w następujący sposób:

self.otherObj = someOtherNewObject; // set it  
MyOtherObject *thingee = self.otherObj; // get it 

Zamiast normalnego, przekazującego wiadomość sposobu:

[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it 

Za kulisami naprawdę wywołujesz metodę, która wygląda tak:

- (void) setOtherObj:(MyOtherObject *)anOtherObject {

    if (otherObject == anOtherObject) {
        return;  
    }

    MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
    otherObject = [anOtherObject retain]; // put the new value in  
    [oldOtherObject release]; // let go of the old object
} // set it

...lub to

- (MyOtherObject *) otherObject {  
    return otherObject;
} // get it
Totalny ból w tyłku. Teraz zrób to dla każdego Ivara w klasie. Jeśli nie zrobisz tego dokładnie dobrze, dostaniesz wyciek pamięci. Najlepiej pozwolić kompilatorowi wykonać pracę.

Widzę, że Numer 1 nie ma Ivara. Zakładając, że to nie jest literówka, jest w porządku, ponieważ dyrektywy @ property / @synthesize będą również deklarować ivar dla Ciebie, za kulisami. uważam, że jest to nowość dla Mac OS X-Snow Leopard i iOS4.

Numer 3 nie ma tych accesorów, więc musisz je napisać sam. Jeśli chcesz, aby metody accessora miały skutki uboczne, wykonaj standardowy taniec zarządzania pamięcią, jak pokazano powyżej, a następnie wykonaj dowolną pracę poboczną, której potrzebujesz, wewnątrz metody accessora. Jeśli zsyntetyzujesz właściwość oraz piszesz własną , to Twoja wersja ma priorytet.

Czy wszystko pokryłem?
 56
Author: willc2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-25 06:43:31

W dawnych czasach miałeś Ivary, a jeśli chcesz pozwolić innym klasom ustawić lub przeczytać je, musisz zdefiniować getter (tj. -(NSString *)foo) i setter(tj. -(void)setFoo:(NSString *)aFoo;).

Jakie właściwości daje Ci setter i getter za darmo (prawie!) wraz z Ivarem. Więc kiedy definiujesz właściwość teraz, możesz ustawić atomiczność (czy chcesz zezwolić na wiele akcji ustawień z wielu wątków, na przykład), a także przypisać/zachować / skopiować semantykę (to znaczy, jeśli setter skopiuje nowa wartość lub po prostu zapisz bieżącą wartość-ważne, jeśli inna klasa próbuje ustawić właściwość string z mutable string, który może zostać zmieniony później).

To właśnie robi @synthesize. Wiele osób pozostawia nazwę ivar tak samo, ale można ją zmienić, pisząc oświadczenie synthesize (np. @synthesize foo=_foo; oznacza utworzenie Ivara o nazwie _foo dla właściwości foo, więc jeśli chcesz przeczytać lub napisać tę właściwość i nie używasz self.foo, będziesz musiał użyć _foo = ... - to po prostu pomaga Złap bezpośrednie odniesienia do ivar, jeśli chcesz tylko przejść przez setter i getter).

Począwszy od Xcode 4.6, nie musisz używać instrukcji @synthesize - kompilator zrobi to automatycznie i domyślnie poprzedzi nazwę Ivara znakiem _.

 16
Author: David H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-24 12:13:18