Как понять этот код быстрого модульного тестирования GCDWebServer?

Я сталкивался с этим кодом:

class WebServerTests: XCTestCase {
    let webServer: GCDWebServer = GCDWebServer()
    var webServerBase: String!

    /// Setup a basic web server that binds to a random port and that has one default handler on /hello
    private func setupWebServer() {
        webServer.addHandlerForMethod("GET", path: "/hello", requestClass: GCDWebServerRequest.self) { (request) -> GCDWebServerResponse! in
            return GCDWebServerDataResponse(HTML: "<html><body><p>Hello World</p></body></html>")
        }

Я смущен webServer.addHandlerForMethod часть. Мне кажется это уже полный вызов функции (webServer.addHandlerForMethod("GET", path: "/hello", requestClass: GCDWebServerRequest.self)). Поэтому я не понимаю, почему это сопровождается закрытием ({(request) -> ...)

РЕДАКТИРОВАТЬ: уточнить, что я не понимаю

Согласно документации на https://github.com/swisspol/GCDWebServer, подпись функции в obj-c:

[webServer addDefaultHandlerForMethod:@"GET"
                         requestClass:[GCDWebServerRequest class]
                    asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {

Поэтому я ожидаю, что его быстрый аналог будет называться примерно так:

        webServer.addHandlerForMethod("GET", path: "/hello", requestClass: GCDWebServerRequest.self, { (request) -> GCDWebServerResponse! in
            return GCDWebServerDataResponse(HTML: "<html><body><p>Hello World</p></body></html>")
        })

т.е. обработка входящего запроса передается в качестве третьего параметра. Но так как замыкание происходит после закрывающего ')', оно совсем не выглядит как часть вызова функции.

Почему сигнатура функции отображается из obj-c, чтобы быстро таким образом?

2 ответа

Решение

В Swift вы можете использовать этот синтаксис, если последний аргумент функции является замыканием. Вот пример из руководства по языку Swift о замыканиях (прокрутите вниз до Trailing Closures):

func someFunctionThatTakesAClosure(closure: () -> ()) {
    // function body goes here
}

// here's how you call this function without using a trailing closure:

someFunctionThatTakesAClosure({
    // closure's body goes here
})

// here's how you call this function with a trailing closure instead:

someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

И еще есть эта заметка:

Если выражение замыкания предоставляется в качестве единственного аргумента функции, и вы предоставляете это выражение в качестве завершающего замыкания, вам не нужно писать пару скобок () после имени функции при вызове функции.

Это означает, что это также разрешено писать так:

someFunctionThatTakesAClosure {
    // closure body
}

… Который помогает обеспечить хороший синтаксис метапрограммирования. Например:

let lock = NSLock()

func locked(closure: () -> ()) {
    lock.lock();
    closure()
    lock.unlock();
}

locked {
    NSLog("Hello, world!")
}

Закрытие - то, где обработка входящего запроса сделана. Он говорит серверу запустить код замыкания, когда GET метод, который запрашивает /hello путь идет.

В коде, который вы разместили в закрытии, создается ответ, который возвращает сервер.

Другие вопросы по тегам