Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

209
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!