O ile wiem, od XCode 4.4 @synthesize
automatycznie wygeneruje metody dostępu do właściwości. Ale właśnie teraz przeczytałem przykładowy kod na temat NSUndoManager
, aw kodzie zauważyłem, że @synthesize
jest dodany jawnie. Lubić:
@interface RootViewController ()
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;
@end
@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;
Jestem teraz zdziwiony ... Kiedy powinienem @synthesize
wyraźnie dodać do mojego kodu?
@sythesize
. Jeśli kod nadal działa, nie jest to konieczne.Odpowiedzi:
Jest wiele odpowiedzi, ale także duże zamieszanie. Postaram się trochę uporządkować (albo zwiększyć bałagan, zobaczymy ...)
Przestańmy mówić o Xcode. Xcode to IDE . clang to kompilator . Ta funkcja, o której rozmawiamy, nazywa się autosyntezą właściwości i jest rozszerzeniem języka Objective-C obsługiwanym przez clang , który jest domyślnym kompilatorem używanym przez Xcode.
Dla jasności, jeśli przełączysz się na gcc w Xcode, nie odniesiesz korzyści z tej funkcji (niezależnie od wersji Xcode). W ten sam sposób, jeśli używasz edytora tekstu i kompilujesz za pomocą clang z wiersza poleceń, Wola.
Dzięki autosyntezie nie musisz jawnie syntetyzować właściwości, ponieważ zostanie ona automatycznie zsyntetyzowana przez kompilator jako
@synthesize propertyName = _propertyName
Istnieje jednak kilka wyjątków:
readwrite z niestandardowym narzędziem pobierającym i ustawiającym
przy świadczeniu zarówno implementację getter i setter niestandardową właściwość nie zostanie automatycznie syntetyzowane
readonly z niestandardowym narzędziem pobierającym
podczas dostarczania niestandardowej implementacji pobierającej dla właściwości tylko do odczytu, nie zostanie to automatycznie zsyntetyzowane
@dynamiczny
podczas używania
@dynamic propertyName
właściwość nie zostanie automatycznie zsyntetyzowana (dość oczywiste, ponieważ@dynamic
i@synthesize
wzajemnie się wykluczają)właściwości zadeklarowane w @protocol
w przypadku zgodności z protokołem żadna właściwość zdefiniowana przez protokół nie będzie automatycznie syntetyzowana
właściwości zadeklarowane w kategorii
jest to przypadek, w którym
@synthesize
dyrektywa nie jest automatycznie wstawiana przez kompilator, ale tych właściwości nie można również zsyntetyzować ręcznie. Chociaż kategorie mogą deklarować właściwości, nie można ich w ogóle syntetyzować, ponieważ kategorie nie mogą tworzyć wartości ivarów. Ze względu na kompletność dodam, że nadal można sfałszować syntezę właściwości przy użyciu środowiska uruchomieniowego Objective-C .nadpisane właściwości (nowe od clang-600.0.51, dostarczane z Xcode 6, dzięki Marc Schlüpmann)
kiedy nadpisujesz właściwość nadklasy, musisz jawnie ją zsyntetyzować
Warto zauważyć, że syntetyzowanie właściwości powoduje automatyczną syntezę kopii zapasowej ivar, więc jeśli brakuje syntezy właściwości, brak będzie również wartości ivar, chyba że zostanie to wyraźnie zadeklarowane.
Z wyjątkiem trzech ostatnich przypadków, ogólna filozofia polega na tym, że za każdym razem, gdy ręcznie określisz wszystkie informacje o właściwości (poprzez zaimplementowanie wszystkich metod
@dynamic
dostępu lub użycie ), kompilator założy, że chcesz mieć pełną kontrolę nad właściwością i wyłączy to.Poza przypadkami wymienionymi powyżej, jedynym innym zastosowaniem wyraźnego określenia
@synthesize
byłoby podanie innej nazwy ivar. Jednak konwencje są ważne, więc radzę zawsze używać domyślnego nazewnictwa.źródło
@synthesize
w kategorii jest to zabronione (nie ma żadnych wartości w kategoriach, jak już zauważyłeś). Dodam notatkę.Jeśli nie użyjesz jawnie,
@synthesize
kompilator zrozumie twoją własność w taki sam sposób, jak napisałeś@synthesize undoManager=_undoManager;
wtedy będziesz mógł pisać w swoim kodzie takie rzeczy jak:
[_undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter
To jest powszechna konwencja.
jeśli piszesz
@synthesize undoManager;
będziesz miał :
[undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter
Osobiście przestaję używać
@synthesize
, ponieważ nie jest to już obowiązkowe. Dla mnie jedynym powodem do użycia@synthesize
jest połączenie plikuiVar
z@property
. Jeśli chcesz wygenerować określony getter i setter dla niego. Ale w danym fragmencie kodu nie maiVar
, myślę, że@synthesize
jest to bezużyteczne. Ale teraz myślę, że nowe pytanie brzmi: „Kiedy używaćiVar
?” I nie mam innej odpowiedzi niż „nigdy” na to pytanie!źródło
@synthesize
ponieważ nie ma już powodu, aby to robić. Również wiodące podkreślenie służy jako miła wizualna flaga, informująca, że pracujesz nad siecią bezpieczeństwa zarządzania pamięcią i wątkami, którą zapewniają właściwości (które powinieneś pominąćinit
idealloc
metody).Kiedy należy
@synthesize
wyraźnie dodać do mojego kodu?Ogólnie rzecz biorąc, jeśli jest to wymagane: prawdopodobnie nigdy nie trafisz na przypadek, w którym jest to potrzebne.
Jest jednak jeden przypadek, w którym może Ci się to przydać.
Załóżmy, że piszesz zarówno niestandardową metodę pobierającą, jak i ustawiającą, ale chcesz, aby zmienna instancji ją wspierała. (W przypadku właściwości atomowej jest to tak proste, jak potrzeba niestandardowego ustawiacza: kompilator zapisze metodę pobierającą, jeśli określisz metodę ustawiającą dla właściwości jednoatomowej, ale nie dla właściwości atomowej).
Rozważ to:
@interface MyObject:NSObject @property (copy) NSString *title; @end @implementation MyObject - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
To nie zadziała, ponieważ
_title
nie istnieje. Określono zarówno metodę pobierającą, jak i ustawiającą, więc Xcode (poprawnie) nie tworzy dla niej zmiennej instancji zapasowej.Masz dwie możliwości zaistnienia. Możesz zmienić na
@implementation
to:@implementation MyObject { NSString *_title; } - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Lub zmień to na:
@implementation MyObject @synthesize title = _title; - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Innymi słowy, chociaż syntetyzacja nie jest nigdy konieczna do celów praktycznych *, może być używana do definiowania zmiennych instancji obsługujących właściwości, gdy udostępniasz metodę pobierającą / ustawiającą. Możesz zdecydować, którego formularza tutaj chcesz użyć.
W przeszłości preferowałem określanie zmiennej instancji w elemencie
@implementation {}
, ale teraz uważam, że@synthesize
trasa jest lepszym wyborem, ponieważ usuwa nadmiarowy typ i wyraźnie wiąże zmienną zapasową z właściwością:@synthesize
spowoduje wygenerowanie błędu kompilatora. Nie skończysz z bezpańskimi zmiennymi instancji.* - Znam jeden przypadek, w którym było to konieczne, związany z podziałem funkcji na kategorie w wielu plikach. I nie zdziwiłbym się, gdyby Apple to naprawił, a nawet już to zrobił.
źródło
atomic
dopiero później dodano jako specyfikator właściwości. Teraz, gdy już tam jest, flaga ostrzegawcza może CięCLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES
zainteresować.OK, kiedy tworzysz nieruchomość ...
@property NSString *name;
Xcode automatycznie zsyntetyzuje iVar, tak jakbyś napisał ...
@synthesize name = _name;
Oznacza to, że możesz uzyskać dostęp do nieruchomości za pomocą ...
self.name; // or _name;
Każda z nich będzie działać, ale w
self.name
rzeczywistości używa tylko metod akcesorów.Jest tylko jeden przypadek, w którym automatyczna synteza nie działa: Jeśli nadpisujesz, ale ustawiasz ORAZ metodę pobierającą, będziesz musiał zsyntetyzować iVar.
Nic ci nie jest, jeśli po prostu zastąpisz ustawiającego lub po prostu zastąpisz metodę pobierającą. Ale jeśli zrobisz jedno i drugie, kompilator tego nie zrozumie i będziesz musiał zsyntetyzować je ręcznie.
Z reguły jednak.
Nie twórz iVars. Wystarczy skorzystać z nieruchomości. Nie syntetyzuj tego.
źródło
Synteza właściwości jest wymagana, gdy właściwość jest zadeklarowana w protokole. Nie zostanie automatycznie zsyntetyzowany w interfejsie implementującym.
źródło
Dziękuję za wyjaśnienie. Miałem podobny problem.
@synthesize firstAsset, secondAsset, audioAsset; @synthesize activityView;
Więc teraz, po ich skomentowaniu, przeszedłem i zastąpiłem każde wystąpienie, na przykład
self.firstAsset Wydaje się, że mógłbym również użyć firstAsset, ale wydaje mi się , że zbyt często tęsknię za „ ”.
źródło
Xcode nie wymaga jawnej
@synthesize
deklaracji.Jeśli nie piszesz,
@synthesize
działa to tak samo, jak:@synthesize manager = _manager;
Przykładowy kod mógł być stary. Wkrótce to zaktualizują.
Możesz uzyskać dostęp do swoich właściwości, takich jak:
[self.manager function];
To jest zalecana konwencja firmy Apple. Przestrzegam tego i polecam, abyś to zrobił!
źródło
[_manager function]
NIE uzyska dostępu do właściwości, zamiast tego będzie uzyskiwać bezpośredni dostęp do podstawowego modułu ivar .[_manager function]
nie używa metod dostępu do właściwości.