通用执行请求,使用泛型

时间:2015-11-07 06:09:14

标签: swift generics

我想使用Generics在swift中创建一个执行请求函数。我想打电话并根据我的回复打开我的枚举结果。但是,我不明白:'不能使用类型的参数列表调用performRequest(NSURLRequest,(结果< __>) - >())'为什么我不能在这里有一个未命名的参数?我也尝试了以下内容:r< MyStruct > ---但我得到一个预期的表达式错误。任何帮助解释上述结果< _>错误将不胜感激。感谢。

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:
    }
}

}

1 个答案:

答案 0 :(得分:1)

问题在于,当您使用performRequest时,您没有向编译器提供有关您打算使用的泛型参数的足够信息。缺少的关键部分是parseResponse需要以与回调相同的方式返回参数化的Result。但是,在您提供的代码段中,parseResponse不是通用的。

我相信这会做你想要的。在这种情况下,我已使用ResultString进行了参数设置,但您可以替换任何其他类型。

// 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;
    }
}