Nuke框架详细解析(三) —— 基于Nuke使用的一个简单示例(二)

322 阅读2分钟
原文链接: www.jianshu.com

版本记录

版本号 时间
V1.0 2018.12.30 星期日

前言

OC对有一个很棒的网络图片加载控件SDWebImage,那么Swift中呢,如果要加载远程网络图片呢?这里接下来几篇就给大家介绍一个Swift中用于加载网络图片的框架 —— Nuke。感兴趣的可以看下面几篇文章。
1. Nuke框架详细解析(一) —— 基本概览(一)
2. Nuke框架详细解析(二) —— 基于Nuke使用的一个简单示例(一)

源码

1. Swift

首先看一下文档结构

下面看一下xib中的内容

接着就是源码了

1. PhotoCell.swift
import UIKit

class PhotoCell: UICollectionViewCell {
  @IBOutlet weak var imageView: UIImageView!
}
2. PhotoGalleryViewController.swift
import UIKit
import Nuke

class PhotoGalleryViewController: UICollectionViewController {
  var photoURLs: [URL] = []
  
  let cellSpacing: CGFloat = 1
  let columns: CGFloat = 3
  var cellSize: CGFloat = 0
  
  var pixelSize: CGFloat {
    get {
      return cellSize * UIScreen.main.scale
    }
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    navigationController?.navigationBar.topItem?.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 {
      $0.dataCache = try! DataCache(name: "com.razeware.Far-Out-Photos.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 {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
    
    let request = ImageRequest(url: photoURLs[indexPath.row], targetSize: CGSize(width: pixelSize, height: pixelSize), contentMode: .aspectFill)
    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.image = ImageLoadingOptions.shared.placeholder
    photoViewController.contentMode = .scaleAspectFit
    
    ImagePipeline.shared.loadImage(
      with: photoURLs[indexPath.row],
      progress: nil) { response, err in
        if err != nil {
          photoViewController.image = ImageLoadingOptions.shared.failureImage
          photoViewController.contentMode = .scaleAspectFit
        } else {
          photoViewController.image = response?.image
          photoViewController.contentMode = .scaleAspectFill
        }
    }
    
    navigationController?.pushViewController(photoViewController, animated: true)
  }
}
3. PhotoViewController.swift
import UIKit

class PhotoViewController: UIViewController {
  var image: UIImage? {
    didSet {
      imageView?.image = image
    }
  }
  
  var contentMode: UIView.ContentMode = .scaleAspectFill {
    didSet {
      imageView?.contentMode = contentMode
    }
  }
  
  @IBOutlet weak var imageView: UIImageView?
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    if let image = image {
      imageView?.image = image
    }
    
    imageView?.contentMode = contentMode
  }
  
  static func instantiate() -> PhotoViewController? {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    return storyboard.instantiateViewController(withIdentifier: "PhotoViewController") as? PhotoViewController
  }
}

这里NASAPhotos.plist中都是存放的地址。

运行起来,如下所示:

后记

本篇主要讲述了基于Nuke使用的一个简单示例,感兴趣的给个赞或者关注~~~