Reputation: 61
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.
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
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