Czy zadeklarowane właściwości wymagają odpowiedniej zmiennej instancji?

101

Czy właściwości w Objective-C 2.0 wymagają zadeklarowania odpowiedniej zmiennej wystąpienia? Na przykład jestem przyzwyczajony do robienia czegoś takiego:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

A co gdybym zamiast tego zrobił to:

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

Czy to jest nadal aktualne? Czy różni się on w jakiś sposób od mojego poprzedniego przykładu?

indragie
źródło
Dlaczego drugi „MyObject.h” jest pogrubiony, a nie „MyObject.m”?
Ríomhaire

Odpowiedzi:

93

Jeśli używasz Modern Objective-C Runtime (to jest iOS 3.x lub nowszy albo 64-bitowy Snow Leopard lub nowszy), nie musisz definiować ivars dla swoich właściwości w takich przypadkach.

Kiedy jesteś @synthesizewłaścicielem, ivar w efekcie zostanie zsyntetyzowany również dla ciebie. W ten sposób można obejść scenariusz „krucho-ivar”. Więcej na ten temat przeczytasz w Cocoa with Love

jbrennan
źródło
71

W swoim interfejsie możesz formalnie zadeklarować zmienną instancji między nawiasami klamrowymi, @propertypoza nawiasami klamrowymi lub jedno i drugie. Tak czy inaczej, stają się atrybutami klasy. Różnica polega na tym, że jeśli zadeklarujesz @property, możesz zaimplementować @synthesizemetodę using , która automatycznie koduje twój getter / setter. Na przykład funkcja ustawiająca automatyczne kodowanie inicjalizuje liczby całkowite i przepływa do zera. JEŻELI zadeklarujesz zmienną instancji i NIE określisz odpowiadającej jej wartości @property, nie możesz użyć @synthesizei musisz napisać własny getter / setter.

Zawsze możesz nadpisać automatycznie zakodowany program pobierający / ustawiający, określając własny. Jest to często wykonywane w przypadku managedObjectContextwłaściwości, która jest ładowana leniwie. W ten sposób deklarujesz swoją managedObjectContextjako właściwość, ale następnie piszesz również -(NSManagedObjectContext *)managedObjectContextmetodę. Przypomnij sobie, że metoda, która ma taką samą nazwę jak zmienna / właściwość instancji, jest metodą „pobierającą”.

Metoda @propertydeklaracji umożliwia również inne opcje, takie jak retaini readonly, których nie ma metoda deklaracji zmiennej instancji. Zasadniczo ivarjest to stary sposób i @propertyrozszerza go i sprawia, że ​​jest bardziej wyszukany / łatwiejszy. Możesz odwołać się albo używając self. prefiks, czy nie, nie ma to znaczenia, o ile nazwa jest unikalna dla tej klasy. W przeciwnym razie, jeśli twoja nadklasa ma taką samą nazwę właściwości jak ty, musisz powiedzieć albo self.name albo super.name, aby określić, o której nazwie mówisz.

W ten sposób zobaczysz coraz mniej osób deklarujących ivars między nawiasami klamrowymi, a zamiast tego przesuniesz się w kierunku tylko określania @property, a następnie wykonywania @synthesize. Nie możesz tego zrobić @synthesizew swojej implementacji bez odpowiedniego pliku @property. Syntezator zna tylko typ atrybutu ze @propertyspecyfikacji. Instrukcja synthesize umożliwia również zmianę nazwy właściwości, dzięki czemu można odwoływać się do właściwości za pomocą jednej nazwy (skrótu) w kodzie, ale na zewnątrz w pliku .h użyj pełnej nazwy. Jednak dzięki naprawdę fajnemu autouzupełnianiu, które ma teraz XCode, jest to mniej korzystne, ale nadal istnieje.

Mam nadzieję, że pomoże to wyjaśnić wszelkie zamieszanie i dezinformację, które tam krążą.

Tata Smerf
źródło
Teraz nie jest obowiązkowe pisanie @synthesize. Więc jak ta odpowiedź jest ważna w tym przypadku!
raaz
NIE MUSISZ deklarować <code> @property ... @ synthesize </code>. Używanie synthesize zwalnia cię z konieczności pisania getter / setter w twojej implementacji. Jeśli nie syntetyzujesz, musisz
wyrzucić
2
@PapaSmurf To nieprawidłowe. Możesz ich używać @property, a nie używać @synthesizei nie wdrażać ich samodzielnie. Kompilator zrobi się automatycznie synthesize, bez konieczności pisania tego.
jbrennan
8

działa w obie strony, ale jeśli nie zadeklarujesz ich w nawiasach klamrowych, nie zobaczysz ich wartości w debugerze w xcode.

rickm
źródło
3

Z dokumentacji:

Ogólnie zachowanie właściwości jest identyczne zarówno w nowoczesnych, jak i starszych środowiskach wykonawczych (zobacz „Wersje środowiska wykonawczego i platformy” w przewodniku programowania środowiska wykonawczego Objective-C). Jest jedna kluczowa różnica: nowoczesne środowisko wykonawcze obsługuje syntezę zmiennych instancji, podczas gdy starsze środowisko wykonawcze nie.

Aby @synthesize działało w starszym środowisku uruchomieniowym, należy podać zmienną instancji o tej samej nazwie i zgodnym typie właściwości lub określić inną istniejącą zmienną instancji w instrukcji @synthesize. W nowoczesnym środowisku wykonawczym, jeśli nie podasz zmiennej instancji, kompilator doda ją za Ciebie.

Charlie Elliott
źródło
3

Jeśli używasz XCode 4.4 lub nowszego, wygeneruje on dla Ciebie kod syntezy zmiennej instancji.

Musisz tylko zadeklarować właściwości takie jak poniżej; wygeneruje syntetyzujący kod i kod deklarujący zmienną instancji.

@property (nonatomic, strong) NSString *name;

wygeneruje syntetyzujący kod jako

@synthesize name = _name;

i możesz uzyskać dostęp do zmiennej instancji za pomocą _name, podobnie jak deklaracja

NSString* _name

ale jeśli zadeklarujesz właściwość tylko do odczytu, to jak

@property (nonatomic, strong, readonly) NSString *name;

wygeneruje kod

@synthesize name;

lub

@synthesize name = name; 

Więc powinieneś mieć dostęp do natychmiastowej nazwy zmiennej bez prefiksu „_” w dowolny sposób, w jaki możesz napisać własny kod syntetyzujący, a następnie kompilator wygeneruje kod za Ciebie. Możesz pisać

@synthesize name = _name;
Shafraz Buhary
źródło
1

Język programowania Objective-C: dyrektywy implementacji właściwości

Istnieją różnice w działaniu syntezy akcesorów, które zależą od środowiska wykonawczego (zobacz także „Różnica w czasie wykonywania”):

  • W starszych środowiskach wykonawczych zmienne instancji muszą być już zadeklarowane w bloku @interface bieżącej klasy. Jeśli istnieje zmienna instancji o tej samej nazwie co właściwość, a jej typ jest zgodny z typem właściwości, jest ona używana - w przeciwnym razie zostanie wyświetlony błąd kompilatora.

  • W przypadku nowoczesnych środowisk wykonawczych (zobacz „Wersje środowiska wykonawczego i platformy” w przewodniku programowania środowiska wykonawczego Objective-C) zmienne instancji są syntetyzowane w razie potrzeby. Jeśli istnieje już zmienna instancji o tej samej nazwie, zostanie użyta.

Nate
źródło