brandonscript
brandonscript

Reputation: 73044

Using .map to map an array of one class to an array of another

I'm new to Swift, and am trying to get my head around using .map. My understanding is that the behaviour is similar to that of Javascript, but maybe I'm not nailing the Swift syntax correctly?

I've created a public Array of my custom class CustomItem (which is a subclass of the type coming back in the response):

public var availableItems: [CustomItem] = []

public static func getAvailableItems(id: String, completion: (items: [CustomItem]) -> ()) -> Void {
    DataConnector.getRelated(type: "users", id: id, relationship: "available") { (response) -> Void in
        availableItems = (response.data?.map { return $0 as! CustomItem })!
        completion(items: availableItems)
    }
}

When I do a po response.data.map { return $0 } in the console with a breakpoint after the response is received, I get:

(lldb) po response.data.map { return $0 }
▿ Optional([<AnSDK.RemoteDataObject: 0x7f8a0b9c16b0>])
  ▿ Some : 1 elements
    ▿ [0] : < AnSDK.RemoteDataObject: 0x7f8a0b9c16b0>

So it definitely seems that part works, but when I try to cast the data object to CustomItem class, I get:

Could not cast value of type 'AnSDK.RemoteDataObject' (0x100abbda0) to 'Project.CustomItem' (0x100882c60).

Here's my CustomItem class just in case:

import AnSDK

public class CustomItem: RemoteDataObject {
    var displayName: String = ""
    var value: Float = 0.0
    var owner: User?
}

If I don't use the ! to force downcast, I get:

RemoteDataObject is not convertible to CustomItem [...] 

... in the compiler.

Upvotes: 1

Views: 356

Answers (1)

Rob Napier
Rob Napier

Reputation: 299693

(I'm really just restating Ben Gottlieb's answer here, but hopefully a bit clearer since I believe some readers were confused by his attempt.)

The message seems fairly clear. You've received an array of AnSDK.RemoteDataObject. As best I can tell from your output, that is the actual class of the objects. You can't just say "it's really this subclass of RDO" unless it really is that subclass. Looking at your code, that seems unlikely. Somewhere in AnSDK it would have to construct a CustomItem and then just happen to return it as a RemoteDataObject. That doesn't appear to be what's happening inside of getRelated. Given your code, I doubt AnSDK knows anything about CustomItem, so how would it have constructed one?

There are numerous ways to fix this depending on what the types really are and how they interact. Ben's solution is one, which basically creates a copy of the object (though in that case, there's no particular reason for CustomItem to be a subclass of RDO, and probably shouldn't be.)

If you just want to add methods to RemoteDataObject, you can do that with extensions. You don't need to create a subclass.

Upvotes: 3

Related Questions