1. data 根据url这个key存储在 fetchLoads中
// A single key may have multiple callbacks. Only download once.
func setup(progressBlock: ImageDownloaderProgressBlock?,with completionHandler: ImageDownloaderCompletionHandler?,for url: URL,options: KingfisherOptionsInfo?,started: ((URLSession,ImageFetchLoad) -> Void)) {
barrierQueue.sync(flags: .barrier) {
let loadobjectForURL = fetchLoads[url] ?? ImageFetchLoad()
let callbackPair = (progressBlock: progressBlock,completionHandler: completionHandler)
loadobjectForURL.contents.append((callbackPair,options ?? KingfisherEmptyOptionsInfo))
//data 根据url这个key存储在 fetchLoads中
fetchLoads[url] = loadobjectForURL
if let session = session {
started(session,loadobjectForURL)
}
}
}
2. 获取每次网络传输过来的数据
func urlSession(_ session: URLSession,dataTask: URLSessionDataTask,didReceive data: Data) {
print("Data......\(data)")
guard let downloader = downloadHolder else {
return
}
if let url = dataTask.originalRequest?.url,let fetchLoad = downloader.fetchLoad(for: url) {
1.将获取的数据data放到downloadHolder.fetchLoad (此处的downloader和downloadHolder是同一块内存地址,所以给downloader拼接获取的网络数据,就相当于给downloadHolder拼接数据)中去。
2.downloadHolder为全局变量,以便于后面获取数据完毕后,可以根据url来取data
fetchLoad.responseData.append(data) //存储每次获取的数据
}
3. 网络数据获取完毕,进行图片解码,图片缓存到本地
//图片数据加载完毕,进入此回调方法
func urlSession(_ session: URLSession,task: URLSessionTask,didCompleteWithError error: Error?) {
guard let url = task.originalRequest?.url else {
retur
}
guard error == nil else {
callCompletionHandlerFailure(error: error!,url: url)
return
}
//数据请求完,在此处完成completionHandler 回调
//在这个函数中,根据url去downloadHolder取image 的data数据,然后解码,存储。
processImage(for: task,url: url)
}
4. data数据处理成image的方法
//数据请求完,在此处完成completionHandler 回调
//对于每一张根据URL取出来的data,在此做图片的预处理。
//当选择图片的默认处理方式时,var image = imageCache[processor.identifier]中的
//processor.identifier = ""处理,具体看identifier的定义说明
private func processImage(for task: URLSessionTask,url: URL) {
guard let downloader = downloadHolder else {
return
}
// We are on main queue when receiving this.
downloader.processQueue.async {
guard let fetchLoad = downloader.fetchLoad(for: url) else {
return
}
self.cleanFetchLoad(for: url)
let data = fetchLoad.responseData as Data
// Cache the processed images. So we do not need to re-process the image if using the same processor.
// Key is the identifier of processor.
var imageCache: [String: Image] = [:]
for content in fetchLoad.contents {
let options = content.options
let completionHandler = content.callback.completionHandler
let callbackQueue = options.callbackdispatchQueue
let processor = options.processor
var image = imageCache[processor.identifier]
if image == nil {
image = processor.process(item: .data(data),options: options)
// Add the processed image to cache.
// If `image` is nil,nothing will happen (since the key is not existing before).
imageCache[processor.identifier] = image
}
if let image = image {
downloader.delegate?.imageDownloader(downloader,didDownload: image,for: url,with: task.response)
if options.backgroundDecode {
let decodedImage = image.kf.decoded(scale: options.scaleFactor)
callbackQueue.safeAsync { completionHandler?(decodedImage,nil,url,data) }
} else {
callbackQueue.safeAsync { completionHandler?(image,data) }
}
} else {
if let res = task.response as? HTTPURLResponse,res.statusCode == 304 {
let notModified = NSError(domain: KingfisherErrorDomain,code: KingfisherError.notModified.rawValue,userInfo: nil)
//数据请求完,在此处完成completionHandler 回调
completionHandler?(nil,notModified,nil)
continue
}
let badData = NSError(domain: KingfisherErrorDomain,code: KingfisherError.badData.rawValue,userInfo: nil)
callbackQueue.safeAsync { completionHandler?(nil,badData,nil) }
}
}
}
}
}