Le proprietà dichiarate richiedono una variabile di istanza corrispondente?


101

Le proprietà in Objective-C 2.0 richiedono la dichiarazione di una variabile di istanza corrispondente? Ad esempio, sono abituato a fare qualcosa del genere:

MyObject.h

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

MyObject.m

@implementation
@synthesize name;
@end

Tuttavia, cosa succede se invece lo facessi:

MyObject.h

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

È ancora valido? Ed è in qualche modo diverso dal mio esempio precedente?


Perché il secondo "MyObject.h" in grassetto non è "MyObject.m"?
Ríomhaire

Risposte:


93

Se stai utilizzando Modern Objective-C Runtime (che è iOS 3.xo versione successiva, oppure Snow Leopard a 64 bit o versione successiva), non è necessario definire ivars per le tue proprietà in casi come questo.

Quando avrai @synthesizela proprietà, l'ivar sarà in effetti sintetizzato anche per te. Questo aggira lo scenario "fragile-ivar". Puoi leggere di più su Cocoa with Love


71

Nella tua interfaccia, puoi dichiarare formalmente una variabile di istanza tra le parentesi graffe, o tramite l' @propertyesterno delle parentesi graffe, o entrambi. In ogni caso, diventano attributi della classe. La differenza è che se dichiari @property, puoi implementare using @synthesize, che codifica automaticamente il tuo getter / setter per te. Il setter del codificatore automatico inizializza i numeri interi e float a zero, per esempio. SE dichiari una variabile di istanza e NON ne specifichi una corrispondente @property, non puoi usare @synthesizee devi scrivere il tuo getter / setter.

Puoi sempre sovrascrivere il getter / setter con codifica automatica specificando il tuo. Questo è comunemente fatto con la managedObjectContextproprietà che viene caricata pigramente. Pertanto, dichiari il tuo managedObjectContextcome proprietà, ma poi scrivi anche un -(NSManagedObjectContext *)managedObjectContextmetodo. Ricorda che un metodo, che ha lo stesso nome di una variabile / proprietà di istanza, è il metodo "getter".

Il @propertymetodo di dichiarazione consente anche altre opzioni, come retaine readonly, che il metodo di dichiarazione della variabile di istanza non offre. Fondamentalmente, ivarè il vecchio modo e lo @propertyestende e lo rende più elaborato / più facile. Puoi fare riferimento a entrambi usando il sé. prefisso o no, non importa fintanto che il nome è univoco per quella classe. Altrimenti, se la tua superclasse ha lo stesso nome di una proprietà come te, allora devi dire come self.name o super.name per specificare di quale nome stai parlando.

Quindi, vedrai sempre meno persone dichiarare ivars tra le parentesi graffe, e invece spostarti verso la semplice specificazione @propertye poi il fare @synthesize. Non puoi fare @synthesizenella tua implementazione senza un corrispondente @property. Il sintetizzatore sa solo che tipo di attributo è dalla @propertyspecifica. L'istruzione synthesize consente anche di rinominare le proprietà, in modo da poter fare riferimento a una proprietà con un nome (abbreviazione) all'interno del codice, ma all'esterno nel file .h utilizzare il nome completo. Tuttavia, con il completamento automatico davvero interessante di XCode ora, questo è un vantaggio minore, ma è ancora lì.

Spero che questo aiuti a chiarire tutta la confusione e la disinformazione che circolano là fuori.


Ora un giorno non è obbligatorio scrivere @synthesize. Allora come è valida questa risposta in quel caso!
raaz

NON DEVI dichiarare <code> @property ... @ synthesize </code>. L'uso di synthesize ti solleva dal dover scrivere un getter / setter nella tua implementazione. Se non sintetizzi, devi lanciare il tuo getter / setter
PapaSmurf

2
@PapaSmurf Non è corretto. Puoi usarli @propertye non usarli @synthesizee non implementarli da solo. Il compilatore si autoalimenterà synthesize, senza doverlo più scrivere.
jbrennan

8

funziona in entrambi i modi, ma se non li dichiari tra parentesi graffe, non vedrai i loro valori nel debugger in xcode.


3

Dalla documentazione:

In generale, il comportamento delle proprietà è identico sia sui runtime moderni che su quelli legacy (vedere "Versioni e piattaforme runtime" nella Guida alla programmazione runtime di Objective-C). C'è una differenza fondamentale: il runtime moderno supporta la sintesi delle variabili di istanza mentre il runtime legacy no.

Affinché @synthesize funzioni nel runtime legacy, è necessario fornire una variabile di istanza con lo stesso nome e tipo compatibile della proprietà o specificare un'altra variabile di istanza esistente nell'istruzione @synthesize. Con il runtime moderno, se non fornisci una variabile di istanza, il compilatore ne aggiunge una per te.


3

Se stai usando XCode 4.4 o successivo, genererà il codice di sintesi della variabile di istanza per te.

Devi solo dichiarare proprietà come sotto; genererà codice di sintesi e variabile di istanza che dichiara il codice per te.

@property (nonatomic, strong) NSString *name;

genererà codice di sintesi come

@synthesize name = _name;

e puoi accedere alla variabile di istanza usando _name, è simile a declare

NSString* _name

ma se dichiari una proprietà di sola lettura è simile

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

genererà codice

@synthesize name;

o

@synthesize name = name; 

Quindi dovresti accedere al nome della variabile istantanea senza il prefisso "_" in qualsiasi modo tu possa scrivere il tuo codice di sintesi, quindi il compilatore genererà il codice per te. tu puoi scrivere

@synthesize name = _name;

1

Il linguaggio di programmazione Objective-C: direttive sull'implementazione delle proprietà

Esistono differenze nel comportamento della sintesi accessoria che dipendono dal runtime (vedere anche "Differenza runtime"):

  • Per i runtime legacy, le variabili di istanza devono essere già dichiarate nel blocco @interface della classe corrente. Se esiste una variabile di istanza con lo stesso nome della proprietà e se il suo tipo è compatibile con il tipo della proprietà, viene utilizzata, altrimenti viene visualizzato un errore del compilatore.

  • Per i runtime moderni (vedere "Versioni e piattaforme di runtime" nella Guida alla programmazione in runtime di Objective-C), le variabili di istanza vengono sintetizzate secondo necessità. Se esiste già una variabile di istanza con lo stesso nome, viene utilizzata.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.