1

I suspect I may be making the same mistake as described by Rob in this post here in that I should be doing this whole thing another way, but with that in mind:

I'm trying to use AlamofireObjectMapper in a generic way. It has a protocol

public protocol Mappable

I then have various model classes that adopt it

class Dog: Mappable
class Cat: Mappable
class Bird: Mappable

I have this method

func loadEntityArray<T: Mappable>(type: T.Type)

and the reason this is generic is because it calls a function load() that needs a completion block that uses this generic param. The 'type' argument is never actually used, but you can't make a func generic without the generic type being in the func's parameter list.

func load(completion:(Response<T, NSError> -> Void))

loadEntityArray is called from another method

func letsgo() { loadEntityArray(Dog.self); loadEntityArray(Cat.self) }

So far so good, this all works. But I want to pass an array of which models to load to letsgo() and I can't work out how to do this. If I change letsgo() to

func letsgo<T:Mappable>(models: [T.Type]) {
  for mod in models {
    loadEntityArray(mod)
  }
}

and then call letsgo() with 1 param like

letsgo([Dog.self])

it works, but as soon as I have an array of 2 or more, I get a compiler error 'cannot convert value of type NSArray to expected argument type [_.Type]' I don't now how I would explicitly type this array either.

letsgo([Dog.self, Cat.self])

I've tried various permutations and nothing seems to work. Am I doing something impossible here? It seems to me the compiler has enough information at compile time for this to work, so I'm not sure if this is a syntax thing or I'm doing something wrong here with generics.

Community
  • 1
  • 1
Brynjar
  • 1,252
  • 1
  • 11
  • 24

2 Answers2

1

Looking at your function :

func letsgo<T:Mappable>(models: [T.Type])

Its model parameter should be an Array of all the same Type. So an array of only Dog Types for example. That's why

letsgo([Dog.self])

works but

letsgo([Dog.self, Cat.self])

won't as it has multiple Types.

The solution :

Use Mappable.Type directly :

func loadEntityArray(type: Mappable.Type) {}

func letsgo(models: [Mappable.Type]) {
    for mod in models {
        loadEntityArray(mod.self)
    }
}

And cast your array of Types as an array of Mappable Types :

letsgo([Dog.self, Cat.self] as [Mappable.Type])

Hope this achieves what you're looking for !

José
  • 471
  • 5
  • 11
  • 1
    Unfortunately not.. The loadEntityArray function needs to be generic itself because it calls the load function which is generic over type T. – Brynjar Apr 10 '16 at 07:55
0

So in the end I came to the conclusion that this is not possible. I changed the code such that I pass in an enum to letsgo() and in a switch statement on that enum I call loadEntityArray(Dog.self) etc. etc. with an explicitly coded call, for each of my possible types. Then the compiler can see all the possible types and is happy.

Brynjar
  • 1,252
  • 1
  • 11
  • 24