Reputation: 67
I would like to make a perform request function in swift using Generics. I want to make the call and switch on my enum Result based on what I get back. However, I don't understand the : 'cannot invoke performRequest with an argument list of type (NSURLRequest, (Result<__>) -> ())' Why can't I have an unnamed parameter here? I have also tried something like the following : r<MyStruct> --- but I then get an expected expression error. Any help explaining the above Result<_> error would be greatly appreciated. Thanks.
enum Result<A> {
case Value
case Error
}
func performRequest<A>(request:NSURLRequest, callback:(Result<A>) -> ()) {
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
callback(parseResponse(data, response: response, error: error))
}
task.resume()
}
class SampleClass {
let request = NSURLRequest(URL: NSURL(string: "www.google.com")!)
init() {
performRequest(request) { r in -------- errors out
switch r {
case .Value:
case .Error:
}
}
}
Upvotes: 1
Views: 280
Reputation: 1176
The problem is that when you use performRequest
, you have not given the compiler enough information about the generic parameter you intend to use. The critical part that is missing is that parseResponse
needs to return a Result
that is parameterised in the same way as the callback. However, in the snippet you provided, parseResponse
is not generic.
I believe this will do what you intend. In this scenario, I've parameterised the Result
with String
, but you can substitute any other type.
// multi-purpose (generic) Result type
enum Result<A>
{
case Value(A) // because you parameterised the enum, you might as well take advantage of the type
case Error
}
// this is a custom parser, you may substitute your own that returns a different type
func parseString( data:NSData?, response:NSURLResponse?, error:NSError? ) -> Result<String> {
if let _ = error {
return Result.Error
}
return Result.Value("Success")
}
// this function is completely generic, but the parser and callback need to be compatible
func performRequest<A>( request:NSURLRequest,
parser:( NSData?, NSURLResponse?, NSError? ) -> Result<A>,
callback:( Result<A> ) -> Void ) {
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
( data, response, error ) -> Void in
callback( parser( data, response, error ) )
}
task.resume()
}
let request = NSURLRequest(URL: NSURL(string: "www.google.com")!)
// actual invocation, now I need to pass in a concrete parser and callback with a specific type
performRequest( request, parser: parseString ) { // parseString returns a Result<String>
r in
switch r {
case .Value( let value ):
// because I passed in a parser that returns a Result<String>, I know that "value" is a String here
print( "Succeeded with value: \(value)" )
break;
case .Error:
print( "an error occurred" )
break;
}
}
Upvotes: 1