混淆关闭和完成句柄

问题描述:

我是一个新的程序员,我很迷茫。混淆关闭和完成句柄

我参加了这个在线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”做(停用后则它建立完成处理“

谢谢

+0

阅读文档应该有助于https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html – kye

这些都是很好的问题!

A closure只是一行代码行的集合(aka block),您可以像变量一样对待它,并像函数一样执行,您可以使用变量名引用闭包,并且可以通过作为函数调用中的参数,就像任何其他变量一样,最终在适当的时候执行代码。闭包可以接受某些参数在其代码中使用,并且可以包含返回值。

实施例:

这是接受两个字符串作为参数并返回字符串的封闭件。

let closure: (String, String) -> String = { (a: String, b: String) -> String in 
               return a + b 
              } 

因此,下面将打印 “你好杰克!”:

print(closure("Hello ", "Jack!")) 

闭包也有一个变量的类型(就像"hello"String1Int)。变量类型基于闭包接受的参数和闭包返回的值。因此,由于上面的闭包接受两个字符串作为参数并返回一个字符串,因此它的变量类型为(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