ios - ¿Cómo puedo lanzar un NSMutableArray a una matriz Swift de un tipo específico?
objective-c (6)
Con Swift 1.2, lo siguiente funcionará:
let mutableArray = NSMutableArray(array: ["a", "b", "c"])
let swiftArray = NSArray(array: mutableArray) as? [String]
Estoy migrando mi proyecto de iOS a Swift. Estoy haciendo esta clase por clase. Cuando llamo a los métodos de Objective C de Swift, muchos de los tipos de Objective C se convierten a sus equivalentes de Swift.
En mi caso, un Objective C NSMutableArray
se convierte en Array<AnyObject>
. Ahora aquí viene mi problema. Dentro de mi clase Swift, obtengo una matriz de un objeto de Objective C. Ahora que estoy en el mundo de Swift, me gustaría convertir esta matriz a un tipo específico en lugar de AnyObject
, porque sé con certeza qué tipo de objetos existen en esta matriz.
¡El compilador no me deja hacer eso! Permítanme simplificar mi problema diciendo que quiero convertirlo a una matriz que contenga cadenas. Esto es lo que intenté:
var strings = myObjcObject.getStrings() as [String]
Recibo el siguiente error del compilador:
''String'' no es idéntico a ''AnyObject''
Tendría que estar de acuerdo con el compilador, ya que String no es idéntico a AnyObject. Pero no veo por qué eso es un problema. Puedo enviar AnyObject a String si quiero, ¿verdad?
También probé:
var strings = myObjcObject.getStrings() as? [String]
Esto parece ser un paso en la dirección correcta, pero getStrings () devuelve un NSMutableArray
así que me NSMutableArray
el siguiente error:
''NSArray'' no es un subtipo de ''NSMutableArray''
¿Hay alguna manera de hacer lo que estoy tratando de hacer aquí?
Puede hacer que esto funcione con un doble downcast, primero en NSArray
, luego en [String]
:
var strings = myObjcObject.getStrings() as NSArray as [String]
Probado en un patio de recreo con:
import Foundation
var objCMutableArray = NSMutableArray(array: ["a", "b", "c"])
var swiftArray = objCMutableArray as NSArray as [String]
Actualizar:
En versiones posteriores de Swift (al menos 1.2), el compilador se quejará de as [String]
. En su lugar, debería usar un if let
con un downcast condicional as?
:
import Foundation
var objCMutableArray = NSMutableArray(array: ["a", "b", "c"])
if let swiftArray = objCMutableArray as NSArray as? [String] {
// Use swiftArray here
}
Si está absolutamente seguro de que su NSMutableArray
se puede convertir a [String]
, ¡puede usar as!
en su lugar (pero probablemente no deberías usar esto en la mayoría de los casos):
import Foundation
var objCMutableArray = NSMutableArray(array: ["a", "b", "c"])
var swiftArray = objCMutableArray as NSArray as! [String]
en Xcode 6.3 utilicé lo siguiente:
var mutableArray = NSMutableArray(array:"1", "2", "3")
let swiftArray = mutableArray as AnyObject as! [String]
para veloz 3
puedes considerar el siguiente código
let array: [String] = nsMutableArrayObject.copy() as! [String]
compactMap
es tu amigo en Swift 4.1 y superior, así como en Swift 3.3 para el caso. Esto significa que no tienes ningún casting doble o forzado.
let mutableArray = NSMutableArray(array: ["a", "b", "c"])
let swiftArray: [String] = mutableArray.compactMap { $0 as? String }
En versiones anteriores de Swift, 2.0-3.2 y 4.0, querrá usar flatMap
para este propósito. El uso es el mismo que compactMap
:
let swiftArray: [String] = mutableArray.flatMap { $0 as? String }
let mutableArray = NSMutableArray()
mutableArray.addObject("Abc")
mutableArray.addObject("def")
mutableArray.addObject("ghi")
if let array = mutableArray as? [String] {
print(array) // ["a", "b", "c"]
}