2015-06-08 7 views
8

consideri un protocollo e una classe che implementa:Swift: la conversione tra le matrici di 'protocollo' e array di attuazione Classe

protocol MyProtocol { 
    var x: Int { get } 
} 

class MyClass : MyProtocol { 
    var x: Int = 5 
} 

Ho un array di tipo [MyClass] e desidero assegnarlo a una variabile di tipo [MyProtocol]. Tuttavia, questo causa un errore quando ha tentato in Playground (XCode 6.3, Swift 1.2):

var classArr: [MyClass] = [MyClass(), MyClass()] 

var protocolArrA: [MyProtocol] = classArr // Causes error: EXC_BAD_INSTRUCTION 
var protocolArrB: [MyProtocol] = classArr as [MyProtocol] // Causes error: EXC_BAD_INSTRUCTION 
var protocolArrC: [MyProtocol] = [MyProtocol](classArr) // Causes error: Cannot find an initializer for type [MyProtocol[ that accepts an argument list of type [MyClass] 

Qual è il modo corretto di fare questo compito a Swift?

P.S. È interessante notare che, quando si utilizza una classe base anziché un protocollo, le espressioni per protocolArrA e protocolArrB funzionano senza errori.

E 'anche interessante notare che l'assegnazione di una nuova istanza di [MyClass] funziona anche bene:

var protocolArrD: [MyProtocol] = [MyClass]() // A-OK! 
+1

riuscito a riprodurre il problema. Sembra molto simile a un bug: -/Il cast manuale tramite 'classArr.map {$ 0 come MyProtocol}' potrebbe essere una soluzione. –

risposta

10

Puoi utilizzare la mappa per trasmettere ogni elemento al tipo desiderato:

protocol MyProtocol { 
    var x: Int { get } 
} 

class MyClass : MyProtocol { 
    var x: Int = 5 
} 

var classArr: [MyClass] = [MyClass(), MyClass()] 

var protocolArrA:[MyProtocol] = classArr.map{$0 as MyProtocol} 
var andBack:[MyClass] = protocolArrA.map{$0 as! MyClass} 

nota, Swift è in grado di dedurre tutti i tipi di array di cui sopra, quindi questo può essere scritto più brevemente come:

var classArr = [MyClass(), MyClass()] 

var protocolArrA = classArr.map{$0 as MyProtocol} 
var andBack = protocolArrA.map{$0 as! MyClass} 
1

provare questo

@objc protocol MyProtocol { 
    var x: Int { get } 
} 

class MyClass : MyProtocol { 
    @objc var x: Int = 5 
} 

Entrambe le opere se si utilizza @objc

var classArr: [MyClass] = [MyClass(), MyClass()]  
var protocolArrA: [MyProtocol] = classArr 
var protocolArrB: [MyProtocol] = classArr as [MyProtocol] 
+0

classArr è di tipo '[MyClass]' di proposito. Non voglio ridefinirlo come '[MyProtocol]'. Il codice attuale è molto più complesso e ho distillato solo le parti che hanno causato il problema (che non è IMHO dipendente dal contesto). –

+0

Aggiornamento la mia risposta – Leo

Problemi correlati