nabil muthanna
nabil muthanna

Reputation: 61

Create an array of swift generics

I have the following struct

struct APIResource<T> {
    let urlRequest: NSMutableURLRequest
    let resource: T
    let parse: (NSData) -> T
 }

I also have the following view controller. It's job it is to ask the network stack to load the resource from the network. Once it is done, it will call the build function to build the appropriate view controller and adds it as a child view controller

 final class LoadingVCL: UIViewController {

init<T>(_ resources: APIResource<T>, build: ((T) -> UIViewController)) {
    super.init(nibName: nil, bundle: nil)
    //ask the network stack for the data
    //once data is loaded, I call the build closure 
    //to return a view controller and add it as a childviewcontroller
}

I am struggling to extend this LoadingVC to accept an array of resources and load them before adding the view controller.

I came across this when following this tutorial.

Edit One

For Instance, suppose I have the following resources

let resourceOne = APIResource<Int>(urlRequest: NSMutableURLRequest(), resource: 1, parse: { _ in return 1})
let resourceTwo = APIResource<Double>(urlRequest: NSMutableURLRequest(), resource: 1, parse: { _ in return 1})
let resourceThree = APIResource<String>(urlRequest: NSMutableURLRequest(), resource: "1", parse: { _ in return "1"})

I am trying to figure out a way for the view controller to accept an array of resources with different types.

Any help would be appreciated. Thanks

Upvotes: 2

Views: 802

Answers (1)

sketchyTech
sketchyTech

Reputation: 5906

As soon as an instance of APIResource<T> is created it has an assigned type and is no longer generic. APIResource<String>, for example, is of a different type to APIResource<Double>. To create an array of mixed types you'll need to use a protocol, e.g.

protocol APIResourceProtocol{}
struct APIResource<T>:APIResourceProtocol {
    let urlRequest: NSMutableURLRequest
    let resource: T
    let parse: (NSData) -> T
}

let resourceOne = APIResource<Int>(urlRequest: NSMutableURLRequest(), resource: 1, parse: { _ in return 1})
let resourceTwo = APIResource<Double>(urlRequest: NSMutableURLRequest(), resource: 1, parse: { _ in return 1})
let resourceThree = APIResource<String>(urlRequest: NSMutableURLRequest(), resource: "1", parse: { _ in return "1"})

let arr:[APIResourceProtocol] = [resourceOne, resourceTwo, resourceThree]

Of course this probably isn't what you want because you're probably wanting to be able to go through an array and use certain methods. Unfortunately, protocols are not generic so it will only be non-generic types that you can leverage this type of behaviour with, e.g.

protocol APIResourceProtocol {
    var urlRequest: NSMutableURLRequest {get set}
}

struct APIResource<T>:APIResourceProtocol {
    var urlRequest: NSMutableURLRequest
    let resource: T
    let parse: (NSData) -> T
}

protocol ResourceType {}

let resourceOne = APIResource<Int>(urlRequest: NSMutableURLRequest(), resource: 1, parse: { _ in return 1})
let resourceTwo = APIResource<Double>(urlRequest: NSMutableURLRequest(), resource: 1, parse: { _ in return 1})
let resourceThree = APIResource<String>(urlRequest: NSMutableURLRequest(), resource: "1", parse: { _ in return "1"})

let arr:[APIResourceProtocol] = [resourceOne, resourceTwo, resourceThree]

arr.map{$0.urlRequest}

Upvotes: 1

Related Questions