【问题标题】:Swift - generics in closureSwift - 闭包中的泛型
【发布时间】:2015-01-11 18:52:44
【问题描述】:

我来自 .NET 世界,所以我对如何在 Swift 中实现泛型感到有些困惑。我正在尝试执行以下操作:

func request<T: Model>(resultHandler: (model: T?) -> ()) {
        var model: T? = nil

        NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: self.url)!) {
            data, response, error in
                if let json = NSString(data: data, encoding: NSUTF8StringEncoding) {
                    model = T(json: json)

                    resultHandler(model: model)
                }
            }.resume()
    }

并按如下方式消费:

var store: HttpStore = HttpStore(url: ...)

store.request {
            model in
                println("Task name: \(model.name!)")
        }

我收到以下错误:

'没有?'没有名为“name”的成员

我明白为什么了。我没有在调用代码中的任何地方将 T 解析为特定类型。在 .NET 中我会做类似 store.request()... 但我不能在 Swift 中这样做。

有没有办法完成我在这里尝试做的事情?

【问题讨论】:

    标签: generics swift closures


    【解决方案1】:

    闭包表达式通常具有以下形式

    { (param_1 : type_1, ..., param_n : type_n ) -> return_type in
        statements
    }
    

    当闭包类型已知或可以从上下文推断时,您可以省略参数类型、返回类型(以及参数周围的括号):

    { param_1, ..., param_n in
        statements
    }
    

    但是在你的代码中

    store.request {
        model in
        // ...
    }
    

    闭包的类型不能从上下文中推断出来,你必须写 它明确为

    store.request {
        (model : Task?) -> () in
        // ...
    }
    

    或者(返回类型()又名Void可以省略):

    store.request {
        (model : Task?) in
        // ...
    }
    

    请注意,在块内,model 是一个可选。正如Antonio 在现已删除的答案中所说, 你将不得不解开可选的,所以

    println("Task name: \(model.name!)")
    

    应该是

    println("Task name: \(model!.name)")
    

    如果model 可能是nil,那么您可以使用可选绑定来测试它:

    if let theModel = model {
        println("Task name: \(theModel.name)")
    }
    

    【讨论】:

    • 这正是我所需要的。我试图在“in”语句中指定类型,但忘记使用括号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 2020-01-19
    • 2015-06-08
    • 1970-01-01
    相关资源
    最近更新 更多