2015-01-11 2 views
0

Я иду из мира .NET, поэтому я немного смущен тем, как генерические средства реализованы в Swift. Я пытаюсь сделать следующее:Swift - generics in close

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!)") 
     } 

Я получаю следующее сообщение об ошибке:

'T?' does not have a member named 'name'

И я понимаю, почему. Я не разрешаю T к определенному типу в любом месте моего кода вызова. В .NET я бы сделал что-то вроде store.request < Задача>() ... Но я не могу этого сделать в Swift.

Есть ли способ выполнить то, что я пытаюсь сделать здесь?

ответ

4

Выражение закрытия обычно имеет вид

{ (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, то вы можете использовать опциональный связывания для тестирования it:

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

Это было именно то, что мне нужно. Я попытался указать тип в выражении «in», но забыл использовать круглые скобки. – lintmouse