Reputation: 3961
I have this enum:
enum ItemType: String {
case image
case movie
var rawValue: String {
switch self {
case .image: return String(kUTTypeImage)
case .movie: return String(kUTTypeMovie)
}
}
}
and this function inside a class
func items<T>(for type: ItemType, completion: ([T]) -> Void) where T: NSSecureCoding {}
Now what I would like to achieve is that if the ItemType is .image I would like the completion to be inferred as of type ([UIImage]) -> Void
otherwise if it is .video I would like it to be inferred as ([URL]) -> Void
Is this possible in any way in Swift? Or what would be an alternative approach to make the completion type infer according to the type provided.
Additional details:
The body of the function uses NSItemProvider loadItem instance method whose closure returns any type conforming to NSSecureCoding. So as long as I can give a type like that I don't care about what type specifically it is.
func items<T>(for type: ItemType, completion: ([T]) -> Void) where T: NSSecureCoding {
itemProviders(for: [type]).forEach { itemProvider in
itemProvider.loadItem(forTypeIdentifier: type.rawValue, options: nil, completionHandler: { (item: T, error: Error!) in
})
}
}
Upvotes: 2
Views: 91
Reputation: 274930
You can't do this because the parameter type
is evaluated at runtime, while at compile time, T
needs to be inferred.
A workaround is to separate this into two methods:
func itemsForImages(completion: ([UIImage]) -> Void) { ... }
func itemsForMovies(completion: ([URL]) -> Void) { ... }
And then determine which method to call:
switch itemType {
case .image:
itemsForImages { images in ... }
case .movies:
itemsForMovies { urls in ... }
}
Another alternative is to have a closure of type ([Any]) -> Void
and the caller needs to cast the parameter to the correct types, but this is not so type safe.
Upvotes: 2