Pierluigi Cifani
Pierluigi Cifani

Reputation: 224

Passing an Array in an Enum

I'm trying to use pass an Enum to a closure, not unlike what Apple does on the guided tour on it's webpage.

This works perfectly fine:

public enum CreateProductResult<A:Product, B:NSError> {
    case product(A)
    case error(B)
}

public typealias CreateProductHandler = (CreateProductResult <Product, NSError>) -> ()

But this won't compile:

public enum FetchProductResult<A:[Product], B:NSError> {
    case product(A)
    case error(B)
}

public typealias FetchProductsHandler = (FetchProductResult <[Product], NSError>) -> ()

The Error:

error: expected a type name or protocol composition restricting 'A'

Why is it wrong when I try to pass in an Array? Do I really have to write a wrapper class around it just to use that as an Enum?

Upvotes: 1

Views: 295

Answers (2)

Antonio
Antonio

Reputation: 72770

An array is a struct, and swift doesn't support inheritance for structs, so it would make no sense specifying a type that must inherit from an array.

You can fix that by letting the product case expect an array, and just specify Product in the generic constraint:

public enum FetchProductResult<A:Product, B:NSError> {
    case product([A])
    case error(B)
}

public typealias FetchProductsHandler = (FetchProductResult <Product, NSError>) -> ()

Note that your code would work if the array were a reference type - just to prove that, if you create a ReferenceArray class (for which I am providing an empty implementation), this code works:

public class ReferenceArray<T> {}

public enum FetchProductResult<A:ReferenceArray<Product>, B:NSError> {
    case product(A)
    case error(B)
}

public typealias FetchProductsHandler = (FetchProductResult <ReferenceArray<Product>, NSError>) -> ()

But wait, a reference type version of the array already exists: NSArray - you could use it if you prefer, but of course it doesn't support generics:

public enum FetchProductResult<A:NSArray, B:NSError> {
    case product(A)
    case error(B)
}

public typealias FetchProductsHandler = (FetchProductResult <NSArray, NSError>) -> ()

so actually not an elegant solution to your specific problem.

Upvotes: 2

Pierluigi Cifani
Pierluigi Cifani

Reputation: 224

This shouldn't be declared as a generic, since you can't pass a struct (which is what an ``Array``` is in Swift). Instead you have to be more specific:

public enum FetchProductResult{
    case product([Product])
    case error(NSError)
}

public typealias FetchProductsHandler = (FetchProductResult) -> ()

Upvotes: 0

Related Questions