混淆关闭和完成句柄
我是一个新的程序员,我很迷茫。混淆关闭和完成句柄
我参加了这个在线iOS开发课程,我正在配置集合视图单元格。 但是,封闭和完成句柄被使用,它从未被提及过。
import UIKit
class PersonCell: UICollectionViewCell {
@IBOutlet weak var img: UIImageView!
func configureCell(imgUrl: String) {
if let url = NSURL(string: imgUrl) {
downloadImg(url)
}
}
func downloadImg(url: NSURL) {
getDataFromURL(url) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) {() -> Void in
guard let data = data where error == nil else {return}
self.img.image = UIImage(data: data)
}
}
}
func getDataFromURL(url: NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError?) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
} .resume()
}
}
有人可以向我解释完成处理程序在“getDataFromURL”函数之后执行的操作。关闭还在做什么?是“(数据,响应,错误)”得到传递? swift如何知道“数据”在“(data,response,error)”中被假设为NSData等? ?! 什么了“dataTaskWithURL”做(停用后则它建立完成处理“
谢谢
这些都是很好的问题!
A closure
只是一行代码行的集合(aka block),您可以像变量一样对待它,并像函数一样执行,您可以使用变量名引用闭包,并且可以通过作为函数调用中的参数,就像任何其他变量一样,最终在适当的时候执行代码。闭包可以接受某些参数在其代码中使用,并且可以包含返回值。
实施例:
这是接受两个字符串作为参数并返回字符串的封闭件。
let closure: (String, String) -> String = { (a: String, b: String) -> String in
return a + b
}
因此,下面将打印 “你好杰克!”:
print(closure("Hello ", "Jack!"))
闭包也有一个变量的类型(就像"hello"
是String
和1
是Int
)。变量类型基于闭包接受的参数和闭包返回的值。因此,由于上面的闭包接受两个字符串作为参数并返回一个字符串,因此它的变量类型为(String, String) -> String
。注意:如果没有返回任何内容(即返回类型为Void
),则可以省略返回类型(因此(Int, String) -> Void
与(Int, String)
相同)。
A completion handler
是您可以传递给某些函数的闭包。当函数完成时,它执行闭包(例如,当一个视图在屏幕上完成动画制作,文件完成下载等时)。
示例:
“完成!”将在视图控制器完成呈现时打印。
let newClosure:() -> Void = {() -> Void in
print("Done!")
}
let someViewController = UIViewController(nibName: nil, bundle: nil)
self.presentViewController(someViewController, animated: true, completion: newClosure)
让我们专注于getDataFromURL
功能,你先写。它需要两个参数:NSData
类型的变量和(NSData?, NSURLResponse?, NSError?) -> Void
类型的闭包。因此,关闭(它被命名为completion
)接受三个参数,类型为NSData?
,NSURLResponse?
和NSError?
,并且不返回任何内容,因为这是您在函数声明中定义闭包的方式。您可以拨打getDataFromURL
。如果您阅读documentation,则会看到在加载任务完成时,将作为第二个参数传递给此函数的闭包执行。 dataTaskWithURL
的函数声明定义了闭包接受和返回的变量类型。在这个闭包中,你接着调用你传递给getDataFromURL
函数的闭包。
在后一个关闭中(当您调用getDataFromURL
时,您在downloadImg
中定义的那个关闭),您正在检查下载的数据是否不为零,如果不是,则将数据设置为图像在UIImageView
。调用dispatch_async(dispatch_get_main_queue(), ...)
只是确保您按照Apple的规范在主线程上设置新映像(您可以在其他位置阅读有关线程的更多信息)。
做出typealias明白这一点很容易:
typealias Handle = (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void
//the func should be
func getDataFromURL(url: NSURL, completion: Handle)
//when you call it. it needs an url and an Handle
getDataFromURL(url:NSURL, completion: Handle)
// so we pass the url and handle to it
getDataFromURL(url) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) {() -> Void in
guard let data = data where error == nil else {return}
self.img.image = UIImage(data: data)
}
}
//setp into the func
func getDataFromURL(url: NSURL, completion: Handle){
// call async net work by pass url
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
// now data/response/error we have and we invoke the handle
completion(data: data, response: response, error: error)
} .resume()
}
hope it be helpful :D
阅读文档应该有助于https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html – kye