版本记录
版本号 | 时间 |
---|---|
V1.0 | 2020.10.10 星期六 |
前言
在我们开发中总有从远程下载图片,OC中有个很成熟的三方框架,大家都知道的
SDWebImage
,同样Swift中也有类似的三方框架Nuke
,接下来几篇我们就一起看一下这个框架。
1. Nuke框架详细解析(一) —— 基本概览(一)
2. Nuke框架详细解析(二) —— 简单使用示例(一)
源码
1. Swift
首先看下工程组织结构
接着看下sb中的内容
下面就是代码了
1. PhotoCell.swift
import UIKit
import Nuke
class PhotoCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
}
2. PhotoGalleryViewController.swift
import UIKit
import Nuke
import ImagePublisher
class PhotoGalleryViewController: UICollectionViewController {
var photoURLs: [URL] = []
let cellSpacing: CGFloat = 1
let columns: CGFloat = 3
var cellSize: CGFloat = 0
var pixelSize: CGFloat {
return cellSize * UIScreen.main.scale
}
var resizedImageProcessors: [ImageProcessing] {
let imageSize = CGSize(width: pixelSize, height: pixelSize)
return [ImageProcessors.Resize(size: imageSize, contentMode: .aspectFill)]
}
override func viewDidLoad() {
super.viewDidLoad()
title = "NASA Photos"
guard
let plist = Bundle.main.url(forResource: "NASAPhotos", withExtension: "plist"),
let contents = try? Data(contentsOf: plist),
let plistSerialized = try? PropertyListSerialization.propertyList(from: contents, options: [], format: nil),
let urlPaths = plistSerialized as? [String]
else {
return
}
photoURLs = urlPaths.compactMap { URL(string: $0) }
let contentModes = ImageLoadingOptions.ContentModes(
success: .scaleAspectFill,
failure: .scaleAspectFit,
placeholder: .scaleAspectFit)
ImageLoadingOptions.shared.placeholder = UIImage(named: "dark-moon")
ImageLoadingOptions.shared.failureImage = UIImage(named: "annoyed")
ImageLoadingOptions.shared.transition = .fadeIn(duration: 0.5)
ImageLoadingOptions.shared.contentModes = contentModes
DataLoader.sharedUrlCache.diskCapacity = 0
let pipeline = ImagePipeline {
let dataCache = try? DataCache(name: "com.raywenderlich.Far-Out-Photos.datacache")
dataCache?.sizeLimit = 200 * 1024 * 1024
$0.dataCache = dataCache
}
ImagePipeline.shared = pipeline
}
}
// MARK: Collection View Data Source Methods
extension PhotoGalleryViewController {
override func collectionView(
_ collectionView: UICollectionView,
numberOfItemsInSection section: Int
) -> Int {
return photoURLs.count
}
override func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "PhotoCell",
for: indexPath) as? PhotoCell else {
return UICollectionViewCell()
}
let request = ImageRequest(
url: photoURLs[indexPath.row],
processors: resizedImageProcessors)
Nuke.loadImage(with: request, into: cell.imageView)
return cell
}
}
// MARK: Collection View Delegate Flow Layout Methods
extension PhotoGalleryViewController: UICollectionViewDelegateFlowLayout {
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
if let layout = collectionViewLayout as? UICollectionViewFlowLayout {
let emptySpace = layout.sectionInset.left + layout.sectionInset.right + (columns * cellSpacing - 1)
cellSize = (view.frame.size.width - emptySpace) / columns
return CGSize(width: cellSize, height: cellSize)
}
return CGSize()
}
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int
) -> CGFloat {
return cellSpacing
}
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int
) -> CGFloat {
return cellSpacing
}
}
// MARK: Collection View Delegate Methods
extension PhotoGalleryViewController {
override func collectionView(
_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath
) {
guard let photoViewController = PhotoViewController.instantiate() else {
return
}
photoViewController.imageURL = photoURLs[indexPath.row]
photoViewController.resizedImageProcessors = resizedImageProcessors
navigationController?.pushViewController(photoViewController, animated: true)
}
}
3. PhotoViewController.swift
import UIKit
import Nuke
import Combine
import ImagePublisher
class PhotoViewController: UIViewController {
var imageURL: URL?
var cancellable: AnyCancellable?
var resizedImageProcessors: [ImageProcessing] = []
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = ImageLoadingOptions.shared.placeholder
imageView.contentMode = .scaleAspectFit
guard let imageURL = imageURL else { return }
loadImage(url: imageURL)
}
func loadImage(url: URL) {
let resizedImageRequest = ImageRequest(
url: url,
processors: resizedImageProcessors)
let resizedImagePublisher = ImagePipeline.shared.imagePublisher(with: resizedImageRequest)
let originalImagePublisher = ImagePipeline.shared.imagePublisher(with: url)
guard let failedImage = ImageLoadingOptions.shared.failureImage else {
return
}
cancellable = resizedImagePublisher.append(
originalImagePublisher)
.map {
($0.image, UIView.ContentMode.scaleAspectFill )
}
.catch { _ in
Just((failedImage, .scaleAspectFit))
}
.sink {
self.imageView.image = $0
self.imageView.contentMode = $1
}
}
static func instantiate() -> PhotoViewController? {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
return storyboard.instantiateViewController(
withIdentifier: "PhotoViewController") as? PhotoViewController
}
}
后记
本篇主要讲述了Swift中的三方框架
Nuke
的简单使用示例,感兴趣的给个赞或者关注~~~
网友评论