Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

208
Vistas
Swift 4.2 weird -.map- behavior

I am having some trouble using .map on a collection in Swift 4.2. Here is what is happening:

I have a property declared like this:

var cbPerifList:[CBPeripheral]!

Later in the code when I write:

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
}

The compiler seems happy and does not complain.

But when I write:

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
    print("HELLO")
}

The compiler complains by displaying this message.

Value of type '[CBPeripheral]' has no member 'identifier'

on the line of code: print(perif.identifier)

Can someone explain what is going on here?

  1. I don't see why adding this line of code makes a difference.

    print("HELLO")

  2. I expect perif to be of type CBPeripheral and not [CBPeripheral] as the error message says.

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

As mentioned in the other answer and in the comments, using forEach or for ... in would be the proper way of traversing through the array.

But to answer your question and to explain why those seemingly identical code snippets behave differently: That is caused by a combination of several facts:

  • [CBPeripheral]! is an implicitly unwrapped optional (IUO), and since Swift 3 those are treated like a regular optional if possible. Compare

    • SE-0054 Abolish ImplicitlyUnwrappedOptional type
    • Swift 3 incorrect string interpolation with implicitly unwrapped Optionals
    • Implicitly unwrapped optional assign in Xcode 8
  • Optional has a map() method:

    func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
    
  • The bodies of multi-statement closures don't participate in type inference.

In the “single-statement” closure

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
}

the compiler tries to infer the closure type from the print expression, and in order to type check perif.identifier, the IUO cbPerifList must be unwrapped to an array.

In the “multi-statement” closure

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
    print("HELLO")
}

the compiler does not try to infer the closure type from the context. Therefore cbPerifList is treated like a regular optional, and map() is the above-mentioned Optional.map method. Inside the closure, perif has the unwrapped type [CBPeripheral]. That is why perif.identifier does not compile with the error message

Value of type '[CBPeripheral]' has no member 'identifier'

You can “help” the compiler with an explicit type annotation

_ = cbPerifList.map { (perif: CBPeripheral) -> Void in
    print(perif.identifier)
    print("HELLO")
}

but – as already said – in this particular case there are better solutions.

over 4 years ago · Santiago Trujillo Denunciar

0

The way map works in Swift (and elsewhere) is that it can map (change) input from one type to another. So in your case, you will call map on your [CBPeripheral] and for each element, the map function will return another value. So, if the identifier is a String, you will end out with an array of Strings.

That is how it should work.

However :)

In your case, you have defined your mapping function like so

(perif) -> Void

Meaning that you will run through your array and call map, with a function that returns nothing. Meaning that the outcome will be an array filled with Void values.

Therefore, as others are suggesting in the comments, if you just want to examine the content of your cbPerifList, you are better of using a for in loop like so

for cbPerif in cbPerifList {
    print(cbPerif.identifier)
}

If however, you're interested in getting an array of the names of your CBPeripherals you can do something like this

let names = cbPerifList.map { $0.identifier }

A comment to the above: To read more about how we can end up just writing { $0.name } have a look at the chapter about Closures in the Swift documentation, or this answer

Hope that helps you.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda