1

Below is the code that works:

let aProvider: () -> [aParticipant] = {
    let results = fetchRequestController.fetchedObjects as! [ParticipantFetchResultsProtocol]

    var newArray: Array<aParticipant> = Array()
    for result in results {
        let obj = result as aParticipant
        newArray.append(obj)
    }

    return newArray
}

With map I tried:

var newArray = results.map({aParticipant($0)})

I get an error: aParticipant cannot be constructed because it has no accessible initializers

Is there a way to accomplish this with map?

Hamish
  • 78,605
  • 19
  • 187
  • 280
user1107173
  • 10,334
  • 16
  • 72
  • 117

2 Answers2

5

As you're using as to upcast result to aParticipant in your for loop, you can simply do the same in a map. Assuming AParticipant is a protocol (sounds like the case from the error you're getting), you just want:

let newArray = results.map { $0 as AParticipant }

Or you can let Swift infer the upcast:

let newArray : [AParticipant] = results.map { $0 }

However, if AParticipant is a superclass type of the elements in your results array, as Alexander Momchliov notes, you can simplify this down to:

let newArray = results as [AParticipant]

An explicit map is required for protocol types however, as they have a different memory structure and therefore each element needs to be converted individually. See both this Q&A and this Q&A for more info.

Also note that I've capitalised AParticipant, as types should be UpperCamelCase – as per the Swift API Design Guidelines.

Community
  • 1
  • 1
Hamish
  • 78,605
  • 19
  • 187
  • 280
  • 2
    Isn't this a case where `as [AParticipant]` can work? – Alexander Aug 04 '16 at 21:09
  • 1
    @AlexanderMomchliov Depends what `AParticipant` is – if it's a protocol, then no it'll require `map` as abstract types have a different memory structure, so an O(n) walk will be required to cast each individual element. If it's just a superclass, then you're indeed right that this could be handled implicitly by the array, I'll update my answer to note this. – Hamish Aug 04 '16 at 21:12
  • 1
    Ah yes, that's what I suspected. To be honest I just always try a cast, see if the compiler yells at me, and then map :p – Alexander Aug 04 '16 at 21:59
0

You can actually collapse the function into a one liner:

return fetchRequestController.fetchedObjects.map { $0 as! Participant }

GetSwifty
  • 7,568
  • 1
  • 29
  • 46