2014-06-22 3 views
6

Ho appena definito un protocollo molto semplice e una classe che utilizza i generici che possono gestire questo protocollo.Protocollo: impossibile assegnare a "X" in "Y" in Swift

Nelle linee contrassegnate con l'errore si otterrà l'errore:. "Non è possibile assegnare a 'bandiera' in 'aObj'

protocol Flag { 
    var flag: Bool {get set} 
} 


class TestFlag<T: Flag> { 

    func toggle(aObj: T) { 

     if aObj.flag { 
      aObj.flag = false; // <--- error 
     } else { 
      aObj.flag = true; // <--- error 
     } 
    } 
} 

Avete un idea del perché e che cosa devo cambiare per risolvere il problema

+0

Basta copiarlo in un parco giochi per testare – Stephan

risposta

6

Dal docs:?

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake.

In questo caso, è possibile aggiungere inout in modo che il toggle è pe rsisted oltre la vostra chiamata di funzione:

func toggle(inout aObj: T) {   
    if aObj.flag { 
     aObj.flag = false; 
    else { 
     aObj.flag = true; 
    } 
} 

si potrebbe avere anche fatto:

func toggle(var aObj: T) { 
} 

ma che potrebbe non ottenere ciò che si voleva.

+2

Perché un downvote? – manojlds

+0

Ho avuto lo stesso problema, ma nel mio caso, aObj era una proprietà della classe. Dovevo fare 'var aObj = self.aObj; aObj.flag = true' –

2

la risposta di manojs è corretta e quindi l'ho accettata.

Tuttavia c'è stata una risposta simile qualche giorno fa con la stessa soluzione ma con un'altra argomentazione (sembra ora cancellata).

L'argomentazione riguardava il fatto che il complatore non può sapere se il protocollo è utilizzato per una classe, una struttura o un enum. Con Swift, i protocolli possono essere applicati su tutti questi tipi. Ma le istanze di struct usano una chiamata di valore e per le istanze di classi (oggetti) è una chiamata per riferimento.

Dal mio punto di vista questa risposta era corretta anche perché è possibile risolvere il problema con una soluzione di 2 °:

@objc 
protocol Flag { 
    var flag: Bool {get set} 
} 

Basta aggiungere l'attriute @obj sul protocollo. Di conseguenza è possibile utilizzare questo protocollo solo per una classe che porta al risultato solo le chiamate by-refernece sono consentite. Pertanto il compilatore non ha più bisogno delle informazioni inout.

Ma ho cercato una soluzione per aumentare il riutilizzo del protocollo e utilizzare ora suggerimenti manojlds.

+4

Puoi anche fare questo ... flag flag: class {...} –