Gettoni e setter di proprietà

Con questa semplice class sto ricevendo l’ avviso del compilatore

Tentativo di modificare / accedere a x all’interno del proprio setter / getter

e quando lo uso in questo modo:

 var p: point = Point() px = 12 

Ottengo un EXC_BAD_ACCESS. Come posso farlo senza espliciti supporti di supporto?

 class Point { var x: Int { set { x = newValue * 2 //Error } get { return x / 2 //Error } } // ... } 

Setter e Getter si applicano alle computed properties ; tali proprietà non hanno memoria nell’istanza – il valore dal getter è inteso per essere calcolato da altre proprietà di istanza. Nel tuo caso, non c’è nessuna x da assegnare.

Esplicitamente: “Come posso farlo senza espliciti supporti di supporto”. Non è ansible – avrete bisogno di qualcosa per il backup della proprietà calcasting. Prova questo:

 class Point { private var _x: Int = 0 // _x -> backingX var x: Int { set { _x = 2 * newValue } get { return _x / 2 } } } 

In particolare, nel REPL Swift:

  15> var pt = Point() pt: Point = { _x = 0 } 16> pt.x = 10 17> pt $R3: Point = { _x = 20 } 18> pt.x $R4: Int = 10 

I setter / getter di Swift sono molto diversi da ObjC. La proprietà diventa una proprietà calcasting che significa che non ha una variabile di supporto come _x come farebbe in ObjC.

Nel codice della soluzione qui sotto puoi vedere che xTimesTwo non memorizza nulla, ma calcola semplicemente il risultato di x .

Vedi Documenti ufficiali sulle proprietà calcolate .

La funzionalità che desideri potrebbe anche essere Property Observers .

Quello di cui hai bisogno è:

 var x:Int var xTimesTwo:Int { set { x = newValue / 2 } get { return x * 2 } } 

È ansible modificare altre proprietà all’interno del setter / getter, che è ciò per cui sono destinate.

È ansible personalizzare il valore impostato utilizzando l’osservatore delle proprietà. Per fare ciò usa “didSet” invece di “set”.

 class Point { var x:Int { didSet { x = x * 2 } } ... 

Per quanto riguarda getter …

 class Point { var doubleX: Int { get { return x / 2 } } ... 

Per elaborare la risposta di GoZoner:

Il tuo vero problema qui è che stai chiamando ricorsivamente il tuo getter.

 var x:Int { set { x = newValue * 2 // This isn't a problem } get { return x / 2 // Here is your real issue, you are recursively calling // your x property's getter } } 

Come il commento del codice suggerito sopra, si sta chiamando all’infinito il getter della proprietà x, che continuerà ad essere eseguito fino a quando non si ottiene un codice EXC_BAD_ACCESS (è ansible vedere lo spinner nell’angolo in basso a destra dell’ambiente del parco giochi Xcode).

Considera l’esempio della documentazione Swift :

 struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct AlternativeRect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } } 

Si noti come la proprietà calcasting al centro non modifica o non restituisce se stessa nella dichiarazione della variabile.

Per sovrascrivere setter e getter per le variabili rapide, utilizzare il codice indicato sotto

 var temX : Int? var x: Int?{ set(newX){ temX = newX } get{ return temX } } 

Abbiamo bisogno di mantenere il valore della variabile in una variabile temporanea, dal momento che provare ad accedere alla stessa variabile il cui getter / setter viene sovrascritto genererà loop infiniti.

Possiamo invocare il setter semplicemente in questo modo

 x = 10 

Getter sarà invocato per sparare sotto una determinata riga di codice

 var newVar = x 

Stai definendo ricorsivamente x con x . Come se qualcuno ti chiedesse quanti anni hai? E tu rispondi “Ho il doppio della mia età”. Che è privo di significato

Devi dire che ho due volte l’età di John o qualsiasi altra variabile tranne te stesso.

le variabili calcolate dipendono sempre da un’altra variabile.


La regola del pollice non è mai l’ accesso alla proprietà stessa all’interno del getter cioè get . Perché ciò innescherebbe un altro get che ne innescherebbe un altro. . . Non stamparlo nemmeno. Perché la stampa richiede anche di “ottenere” il valore prima che possa stamparlo!

 struct Person{ var name: String{ get{ print(name) // DON'T do this!!!! return "as" } set{ } } } let p1 = Person() 

In quanto ciò darebbe il seguente avviso:

Tentativo di accedere al ‘nome’ dall’interno del proprio getter.

L’errore sembra vago come questo:

inserisci la descrizione dell'immagine qui

In alternativa potresti voler usare didSet . Con didSet otterrai una didSet per il valore che è stato impostato prima e appena impostato. Per ulteriori vedere questa risposta .

Prova a usare questo:

 var x:Int! var xTimesTwo:Int { get { return x * 2 } set { x = newValue / 2 } } 

Questa è fondamentalmente la risposta di Jack Wu, ma la differenza è che nella risposta di Jack Wu la sua variabile x è var x: Int , nella mia, la mia variabile x è così: var x: Int! , quindi tutto quello che ho fatto è stato renderlo un tipo opzionale.

Aggiornamento: Swift 4

Nel setter di class inferiore e getter viene applicato a sideLength variabile

 class Triangle: { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { //initializer method self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { // getter return 3.0 * sideLength } set { //setter sideLength = newValue / 4.0 } } 

Creazione di oggetti

 var triangle = Triangle(sideLength: 3.9, name: "a triangle") 

procacciatore

 print(triangle.perimeter) // invoking getter 

Setter

 triangle.perimeter = 9.9 // invoking setter 

I setter e i getter di Swift si applicano alle proprietà / variabili calcolate. Queste proprietà / variabili non sono effettivamente memorizzate nella memoria, ma piuttosto calcolate in base al valore delle proprietà / variabili memorizzate.

Vedi la documentazione di Apple Swift sull’argomento: Dichiarazioni veloci Swift .

Ecco una risposta teorica. Questo può essere trovato qui

Una proprietà {get set} non può essere una proprietà costante memorizzata. Dovrebbe essere una proprietà calcasting e sia il get che il set dovrebbero essere implementati.