Tengo algunos problemas para usar .map en una colección en Swift 4.2. Esto es lo que está pasando:
Tengo una propiedad declarada así:
var cbPerifList:[CBPeripheral]!Más adelante en el código cuando escribo:
_ = cbPerifList.map { (perif) -> Void in print(perif.identifier) }El compilador parece feliz y no se queja.
Pero cuando escribo:
_ = cbPerifList.map { (perif) -> Void in print(perif.identifier) print("HELLO") }El compilador se queja mostrando este mensaje.
Value of type '[CBPeripheral]' has no member 'identifier'en la línea de código: print(perif.identifier)
¿Alguien puede explicar qué está pasando aquí?
No veo por qué agregar esta línea de código hace la diferencia.
imprimir("HOLA")
Espero que perif sea del tipo CBPeripheral y no [CBPeripheral] como dice el mensaje de error.
Como se mencionó en la otra respuesta y en los comentarios, usar forEach o for ... in sería la forma correcta de atravesar la matriz.
Pero para responder a su pregunta y explicar por qué esos fragmentos de código aparentemente idénticos se comportan de manera diferente: eso es causado por una combinación de varios hechos:
[CBPeripheral]! es un opcional implícitamente desenvuelto (IUO) y, desde Swift 3, se trata como un opcional normal si es posible. Comparar
Optional tiene un método map() :
func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?Los cuerpos de los cierres de sentencias múltiples no participan en la inferencia de tipos .
En el cierre de “single-statement”
_ = cbPerifList.map { (perif) -> Void in print(perif.identifier) } el compilador intenta inferir el tipo de cierre a partir de la expresión de print , y para escribir check perif.identifier , IUO cbPerifList debe desenvolverse en una matriz.
En el cierre “multi-statement”
_ = cbPerifList.map { (perif) -> Void in print(perif.identifier) print("HELLO") } el compilador no intenta inferir el tipo de cierre del contexto. Por lo tanto cbPerifList se trata como un opcional regular, y map() es el método Optional.map mencionado anteriormente. Dentro del cierre, perif tiene el tipo sin [CBPeripheral] . Es por eso que perif.identifier no compila con el mensaje de error
El valor de tipo '[CBPeripheral]' no tiene un 'identificador' de miembro
Puede "ayudar" al compilador con una anotación de tipo explícita
_ = cbPerifList.map { (perif: CBPeripheral) -> Void in print(perif.identifier) print("HELLO") }pero, como ya se dijo, en este caso particular hay mejores soluciones.
La forma en que map funciona en Swift (y en otros lugares) es que puede mapear (cambiar) la entrada de un tipo a otro. Entonces, en su caso, llamará al map en su [CBPeripheral] y para cada elemento, la función del map devolverá otro valor. Entonces, si el identifier es una String , terminará con una matriz de Cadenas.
Así es como debería funcionar.
Sin embargo :)
En su caso, ha definido su función de mapeo así
(perif) -> VoidLo que significa que ejecutará su matriz y llamará al mapa, con una función que no devuelve nada. Lo que significa que el resultado será una matriz llena de valores Void.
Por lo tanto, como otros sugieren en los comentarios, si solo desea examinar el contenido de su cbPerifList , es mejor que use un bucle for in como ese
for cbPerif in cbPerifList { print(cbPerif.identifier) } Sin embargo, si está interesado en obtener una matriz de los nombres de sus CBPeripherals , puede hacer algo como esto
let names = cbPerifList.map { $0.identifier } Un comentario a lo anterior: para leer más sobre cómo podemos terminar simplemente escribiendo { $0.name } , consulte el capítulo sobre Cierres en la documentación de Swift, o esta respuesta
Espero que eso te ayude.