Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

216
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda