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, nil, url, 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, url, nil)
continue
}
let badData = NSError(domain: KingfisherErrorDomain, code: KingfisherError.badData.rawValue, userInfo: nil)
callbackQueue.safeAsync { completionHandler?(nil, badData, url, nil) }
}
}
}
}
}