2014-10-08 13 views
15

Quando creo un setter come tale:Creare un setter Solo a Swift

var masterFrame:CGRect{ 
     set{ 
      _imageView.frame = newValue 
      _scrollView.frame = newValue 
     } 
    } 

sua costringendomi a fare un getter, che io non voglio fare.

C'è un modo per creare un setter in Swift senza un getter?

+2

No - suona come voi sarebbe meglio con un metodo. –

+0

Hmm Suppongo che questa sia l'UNICA cosa che odierò di veloce allora! – Aggressor

+2

Quando si utilizzano le proprietà di sola scrittura? Non ho mai avuto occasione di farlo. –

risposta

3

Una proprietà di solo set non sembra avere senso. Probabilmente dovresti usare un metodo per questo.

Oppure, basta fare il compilatore felice e aggiungere un getter che non avete mai chiamare:

get { 
    return _imageView.frame 
} 
+0

Questa è la mia soluzione attuale ma vorrei non averlo anche io :( – Aggressor

+3

Puoi anche mettere una chiusura '' 'didset''' sul frame di imageView che aggiorna le scrollView frame o utilizzare AutoLayout con vincoli per renderli uguali –

+0

I setter sono per l'impostazione.Gli osservatori di proprietà sono per l'esecuzione di attività prima/dopo l'accesso a una proprietà. Si dovrebbe sicuramente usare 'didSet' per ciò che si sta tentando di fare. – Andrew

12

Dal docs:

Il getter viene utilizzato per leggere il valore, e il setter viene utilizzato per scrivere il valore. La clausola setter è facoltativa e quando è necessario un solo getter è necessario, è possibile omettere entrambe le clausole e semplicemente restituire direttamente il valore richiesto, come descritto in Proprietà calcolate di sola lettura. Ma se si fornisce una clausola setter, è necessario fornire anche una clausola getter .

+21

Ci deve essere un modo per aggirare questo.Ci sono molti casi che voglio setter senza getter ... – Aggressor

7

Per avere una "proprietà setter-only", si può solo avere una semplice funzione che imposta il valore; per esempio, se abbiamo una proprietà privata denominata value, siamo in grado di avere un metodo setter chiamato, configureWithValue(value:String) che aggiorna la proprietà, ma non consente l'accesso al di fuori alla proprietà:

private var value:String 

func configureWithValue(value:String) { 
    self.value = value 
} 
8

Beh, se devo proprio, Lo userei.

public subscript(index: Int) -> T { 
    get { 
     fatalError("You cannot read from this object.") 
    } 
    set(v) { 
    } 
} 

La verifica avviene in fase di esecuzione, ma chiaramente la vostra intenzione consegnare all'utente il codice.

Sarebbe bello se il compilatore Swift supporta alcuni attributi sui getter.

public subscript(index: Int) -> T { 
    @availability(*,unavailable) 
    get { 
     fatalError("You cannot read from this object.") 
    } 
    set(v) { 
    } 
} 

Ma questo non funziona attualmente: P (Swift 1.2, la versione 6.3.1 (6D1002))

Il modo più semplice e veloce sarebbe chiedere questo su Apple Radar e Developer Forum di Apple.

3

Sicuro. Si può solo restituire un nullo e fare il tipo di optional:

var color: MyColorEnum? { 
    get { return nil } 
    set { 
     switch newValue! { 
     case .Blue: 
     view.backgroundColor = UIColor.blueColor() 
     case .Red: 
     view.backgroundColor = UIColor.redColor() 
     } 
    } 
    } 

In alternativa, è possibile utilizzare didSet per evitare il problema tutti insieme:

var color: MyColorEnum! { 
    didSet { 
    switch color { 
     case .Blue: 
     view.backgroundColor = UIColor.blueColor() 
     case .Red: 
     view.backgroundColor = UIColor.redColor() 
     } 
    } 
} 
0

si può tornare nil da get:

var input: CGRect? { 
    set(value) { 
     guard let value = value else { return } 
     // process the value here 
    } 
    get { 
     return nil 
    } 
} 
0

Ho trovato un'eccezione in cui mi piace molto una variabile solo setter, ovvero quando sto passando una chiusura come unico parametro in un metho d al solo scopo di salvarlo per un'esecuzione successiva.

implemento come un metodo come segue:

typealias ThemeSetter =() ->() 

class Theme { 

    fileprivate var themeSetters:[ThemeSetter] = [] 

    class var shared: Theme { 
     struct Singleton { 
      static let instance = Theme() 
     } 
     return Singleton.instance 
    } 
     ... 

    func setColor(_ entry:@escaping ThemeSetter) { 
     entry() 
     themeSetters.append(entry) 
    } 
} 

posso quindi chiamare il metodo come segue:

Theme.shared.setColor({ 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    }) 

Ma non mi piace chiudere paretheses dopo la parentesi chiusa, dal momento che Potrei avere molte linee nella chiusura.

Quindi, conoscendo Trailing Chiusure posso solo cambiare il codice di simile a questa:

Theme.shared.setColor() { 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    } 

Questo è perfettamente a posto ed è la sintassi che Apple mostra per Trailing Chiusure. Poiché non v'è solo l'un parametro e di essere il minimalista che io sono tentato di rendere il codice ancora più snella e ridurlo a questo:

Theme.shared.setColor { 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    } 

che è di nuovo come Apple dimostra di fare Trailing Chiusure; Tranne che, in questo modo viene solitamente utilizzato per una sorta di Predicato in cui la chiusura viene utilizzata per indicare al metodo come eseguire un ordinamento o quando la chiusura viene utilizzata alla fine di una chiamata di funzione asincrona come chiusura di completamento. Quello che voglio è assegnare la chiusura a ... Qualcosa.

Se sostituisco il metodo per setColor con una variabile che assomiglia a questo:

var setColor:ThemeSetter? { 
     didSet { 
      if setColor != nil { 
       setColor?() 
       themeSetters.append(setColor!) 
       setColor = nil 
      } 
     } 
    } 

Ora la chiamata si presenta così:

Theme.shared.setColor = { 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    } 

che equivale a segno significa che la differenza di essere. Mostra che sto assegnando una chiusura e non eseguo alcuna funzione che utilizza la chiusura, anche se lo fa. : ') < - bisogno di emoticon qui.

Note finali: Questo in realtà non ha nulla a che fare con le chiusure, mostra solo come è possibile impostare un setter solo variabile, tranne che restituisce comunque un valore nullo. Non è inteso per proteggere la classe dall'avere l'utente che accede alla variabile per leggere come sarebbe un vero setter. Inoltre, perdona il tutorial su Trailing Closures and Singletons.

Potrei non ottenere abbastanza voti in modo che sia la risposta corretta, ma perché la risposta corretta è "No, non puoi! È necessario utilizzare una chiamata al metodo!". Dico "Ni" a chi ha bisogno di tutta quella sintassi. Basta usare una variabile e non leggerla di nuovo o se lo fai, non farlo restituire nulla. un po 'come la risposta di Rudolf Adamkovic, che ha ottenuto 0 voti.

4

Uso didSet invece:

var masterFrame:CGRect { 
     didSet { 
      _imageView.frame = masterFrame 
      _scrollView.frame = masterFrame 
     } 
    }