请帮我理解这段代码

时间:2016-12-24 14:11:06

标签: ios swift callback completionhandler

public func fetchAllRooms(completion: ([RemoteRoom]?) -> Void) {
  let url = NSURL(string: "http://localhost:5984/rooms/_all_docs?include_docs=true")!

  let urlRequest = NSMutableURLRequest(
    URL: url,
    cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
    timeoutInterval: 10.0 * 1000)
  urlRequest.HTTPMethod = "GET"
  urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")

  let task = urlSession.dataTaskWithRequest(urlRequest)
    { (data, response, error) -> Void in
    guard error == nil else {
      print("Error while fetching remote rooms: \(error)")
      completion(nil)
      return
    }

    guard let json = try? NSJSONSerialization.JSONObjectWithData(data!,
      options: []) as? [String: AnyObject] else {
        print("Nil data received from fetchAllRooms service")
        completion(nil)
        return
    }

    guard let rows = json["rows"] as? [[String: AnyObject]] {
      print("Malformed data received from fetchAllRooms service")
      completion(nil)
      return
    }

    var rooms = [RemoteRoom]()
    for roomDict in rows {
      rooms.append(RemoteRoom(jsonData: roomDict))
    }

    completion(rooms)
  }

  task.resume()
}

我在Swift中很新。

fetchAllRooms函数接受另一个名称完成的函数,它接受一个参数数组RemoteRoom并返回void。

现在最后,使用参数RemoteRoom调用完成块(语法似乎是Objective c中的块回调)。 RemoteRoom初始化&完成块被称为completion(rooms)。但是完井区的主体在哪里?当行completion(rooms)被执行时要执行的行是什么。

3 个答案:

答案 0 :(得分:3)

完成块的主体是传递函数或闭包的主体。以下示例都做同样的事情:

func fetch(completion: (Int) -> Int) {
    print("executing fetch")

    let result = completion(5)
    print("completion(5) returns \(result)")
}

// calling it passing a function with the right signature
func addOne(i: Int) -> Int {
    return i + 1
}

fetch(completion: addOne)

// passing a closure
fetch(completion: { i in return i + 1 })

// same with trailing closure syntax
fetch() { i in
    return i + 1
}

// () isn't needed if completion is the only parameter
fetch { i in
    return i + 1
}

// simplified closure removing parameter name and return
fetch { $0 + 1 }

答案 1 :(得分:1)

调用该函数时,调用(执行)completion的块部分。 completion(rooms)的调用将执行您已调用此函数fetchAllRooms的完成块。

self.fetchAllRooms() { rooms in
    //When you call completion(rooms) this block will be executed and you get [RemoteRoom] 
    in rooms instance

    //do something with rooms instance here
} 

答案 2 :(得分:1)

Objective-C块和Swift闭包是一回事,名称不同,语法略有不同,但它们是可以互换的。

在Objective-C中,系统有一个UIView动画类方法animateWithDuration:animations:。想象一下它的实现:

@interface UIView

+(void) animateWithDuration: (int) duration, animations: (void (^)(void)) animations {
   //set up animation
   animations();
   //finish animations
}

动画的正文块在哪里?

它由来电者提供。行animations()调用传入方法的块。

fetch()函数也是如此。它需要一个名为completion的块/闭包。 fetch函数使用异步URLSession(Objective-C中的NSURLSession)dataTask来下载数据,并为数据任务提供完成处理程序。

数据任务完成后,数据任务的完成处理程序代码将运行。在该完成处理程序中,fetch()函数调用传递给它的完成处理函数。 (这里有两个级别的完成处理程序。)这是在Objective-C和Swift中使用aysnc库的一种非常常见的模式。

Swift有一个“尾随闭包”语法,就像Objective-C一样。在这两种语言中,如果函数的最后一个参数是块/闭包,则可以在括号外拉出块闭包,跳过参数标签,并简单地为块/闭包提供大括号。在Objective-C中,你必须在块之前添加那个可怕的^以使编译器满意,但除此之外两者非常相似。