2015-07-03 26 views
6

ho una semplice classe di sottorapida setter causando EXC_BAD_ACCESS

import Foundation 

public class UsefulClass: NSObject{ 
    var test:NSNumber{ 
     get{return self.test} 
     set{ 
      println(newValue) 
      self.test = newValue 
     } 
    } 
    override init() { 
     super.init() 
     self.test = 5; 
    } 
} 

e sto inizializzazione qui

import UIKit 

class ViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     var testClass = UsefulClass() 
    } 
} 

Ma si traduce in Xcode stampare 200 5s e poi schiantarsi a causa di codice EXC_BAD_ACCESS = 2. Perché succede?

risposta

7

@vadian ha fornito una soluzione nella sua risposta, che dovrebbe risolvere il problema. Lasciatemi solo spiegare cosa sta succedendo.

Hai creato una proprietà calcolata, cioè una proprietà che non è supportata da una variabile, invece sia il getter che il setter eseguono qualche elaborazione, di solito su un'altra proprietà memorizzata, per restituire rispettivamente un valore e impostare un nuovo valore.

Questa è la vostra proprietà calcolata:

var test: NSNumber { 
    get { return self.test } 
    set { 
     println(newValue) 
     self.test = newValue 
    } 
} 

Guardate l'attuazione getter:

return self.test 

Che cosa fa? Legge la proprietà test dell'istanza corrente e la restituisce. Qual è la proprietà test? È questo:

var test: NSNumber { 
    get { return self.test } 
    set { 
     println(newValue) 
     self.test = newValue 
    } 
} 

Sì, è la stessa proprietà. Ciò che fa il tuo getter è di chiamarsi in modo ricorsivo e indefinito fino a quando si verifica un arresto anomalo in fase di runtime.

La stessa regola vale per il setter:

self.test = newValue 

mantiene invocando per sé, fino a quando l'applicazione si blocca.

+0

Vedo, quindi non c'è modo di sovrascrivere il setter in Swift per fare qualcosa come set {self.test = newValue - 7} senza un'altra proprietà memorizzata? – user3211122

+0

Oh nvm, http://stackoverflow.com/questions/24006234/what-is-the-purpose-of-willset-and-didset-in-swift è stato davvero utile. Quindi set/get sono solo metodi e didSet/willSet sono legati a ivars. – user3211122

3

Le variabili Swift sono proprietà sintetizzate per impostazione predefinita. Nella maggior parte dei casi questo è sufficiente (si consiglia di preferire i tipi Swift)

var test: Int 

override init() { 
    super.init() 
    test = 5 
} 

Se avete bisogno di fare qualcosa dopo una variabile è impostata, utilizzare

var test: Int { 
    didSet{ 
     println("\(oldValue) - \(newValue)") 
    } 
} 

il codice imposta la variabile in modo permanente chiamare il setter che chiama il setter che ...