Refactors loading operations to inherit from Roxas’ RSTLoadOperation
This commit is contained in:
parent
882c6e74e6
commit
54da484423
@ -47,7 +47,6 @@
|
|||||||
BF3540081C5DAFAD00C1184C /* PauseTransitionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3540071C5DAFAD00C1184C /* PauseTransitionCoordinator.swift */; };
|
BF3540081C5DAFAD00C1184C /* PauseTransitionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3540071C5DAFAD00C1184C /* PauseTransitionCoordinator.swift */; };
|
||||||
BF59425C1E09BB810051894B /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942581E09BB810051894B /* Action.swift */; };
|
BF59425C1E09BB810051894B /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942581E09BB810051894B /* Action.swift */; };
|
||||||
BF5942641E09BBB10051894B /* LoadControllerSkinImageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942611E09BBB10051894B /* LoadControllerSkinImageOperation.swift */; };
|
BF5942641E09BBB10051894B /* LoadControllerSkinImageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942611E09BBB10051894B /* LoadControllerSkinImageOperation.swift */; };
|
||||||
BF5942651E09BBB10051894B /* LoadImageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942621E09BBB10051894B /* LoadImageOperation.swift */; };
|
|
||||||
BF5942661E09BBB10051894B /* LoadImageURLOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942631E09BBB10051894B /* LoadImageURLOperation.swift */; };
|
BF5942661E09BBB10051894B /* LoadImageURLOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942631E09BBB10051894B /* LoadImageURLOperation.swift */; };
|
||||||
BF59426A1E09BBD00051894B /* GridCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942681E09BBD00051894B /* GridCollectionViewCell.swift */; };
|
BF59426A1E09BBD00051894B /* GridCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942681E09BBD00051894B /* GridCollectionViewCell.swift */; };
|
||||||
BF59426B1E09BBD00051894B /* GridCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942691E09BBD00051894B /* GridCollectionViewLayout.swift */; };
|
BF59426B1E09BBD00051894B /* GridCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5942691E09BBD00051894B /* GridCollectionViewLayout.swift */; };
|
||||||
@ -153,7 +152,6 @@
|
|||||||
BF3540071C5DAFAD00C1184C /* PauseTransitionCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseTransitionCoordinator.swift; path = "Pause Menu/Segues/PauseTransitionCoordinator.swift"; sourceTree = "<group>"; };
|
BF3540071C5DAFAD00C1184C /* PauseTransitionCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseTransitionCoordinator.swift; path = "Pause Menu/Segues/PauseTransitionCoordinator.swift"; sourceTree = "<group>"; };
|
||||||
BF5942581E09BB810051894B /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Action.swift; path = Components/Action.swift; sourceTree = "<group>"; };
|
BF5942581E09BB810051894B /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Action.swift; path = Components/Action.swift; sourceTree = "<group>"; };
|
||||||
BF5942611E09BBB10051894B /* LoadControllerSkinImageOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoadControllerSkinImageOperation.swift; path = Components/Loading/LoadControllerSkinImageOperation.swift; sourceTree = "<group>"; };
|
BF5942611E09BBB10051894B /* LoadControllerSkinImageOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoadControllerSkinImageOperation.swift; path = Components/Loading/LoadControllerSkinImageOperation.swift; sourceTree = "<group>"; };
|
||||||
BF5942621E09BBB10051894B /* LoadImageOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoadImageOperation.swift; path = Components/Loading/LoadImageOperation.swift; sourceTree = "<group>"; };
|
|
||||||
BF5942631E09BBB10051894B /* LoadImageURLOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoadImageURLOperation.swift; path = Components/Loading/LoadImageURLOperation.swift; sourceTree = "<group>"; };
|
BF5942631E09BBB10051894B /* LoadImageURLOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoadImageURLOperation.swift; path = Components/Loading/LoadImageURLOperation.swift; sourceTree = "<group>"; };
|
||||||
BF5942681E09BBD00051894B /* GridCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GridCollectionViewCell.swift; path = "Components/Collection View/GridCollectionViewCell.swift"; sourceTree = "<group>"; };
|
BF5942681E09BBD00051894B /* GridCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GridCollectionViewCell.swift; path = "Components/Collection View/GridCollectionViewCell.swift"; sourceTree = "<group>"; };
|
||||||
BF5942691E09BBD00051894B /* GridCollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GridCollectionViewLayout.swift; path = "Components/Collection View/GridCollectionViewLayout.swift"; sourceTree = "<group>"; };
|
BF5942691E09BBD00051894B /* GridCollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GridCollectionViewLayout.swift; path = "Components/Collection View/GridCollectionViewLayout.swift"; sourceTree = "<group>"; };
|
||||||
@ -306,9 +304,8 @@
|
|||||||
BF5942601E09BBA80051894B /* Loading */ = {
|
BF5942601E09BBA80051894B /* Loading */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF5942611E09BBB10051894B /* LoadControllerSkinImageOperation.swift */,
|
|
||||||
BF5942621E09BBB10051894B /* LoadImageOperation.swift */,
|
|
||||||
BF5942631E09BBB10051894B /* LoadImageURLOperation.swift */,
|
BF5942631E09BBB10051894B /* LoadImageURLOperation.swift */,
|
||||||
|
BF5942611E09BBB10051894B /* LoadControllerSkinImageOperation.swift */,
|
||||||
);
|
);
|
||||||
name = Loading;
|
name = Loading;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -752,7 +749,6 @@
|
|||||||
BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */,
|
BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */,
|
||||||
BF6866171DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift in Sources */,
|
BF6866171DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift in Sources */,
|
||||||
BF59427D1E09BC830051894B /* ControllerSkin.swift in Sources */,
|
BF59427D1E09BC830051894B /* ControllerSkin.swift in Sources */,
|
||||||
BF5942651E09BBB10051894B /* LoadImageOperation.swift in Sources */,
|
|
||||||
BFCEA67E1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift in Sources */,
|
BFCEA67E1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift in Sources */,
|
||||||
BF1173501DA32CF600047DF8 /* ControllersSettingsViewController.swift in Sources */,
|
BF1173501DA32CF600047DF8 /* ControllersSettingsViewController.swift in Sources */,
|
||||||
BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */,
|
BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */,
|
||||||
|
|||||||
@ -10,6 +10,17 @@ import UIKit
|
|||||||
|
|
||||||
import DeltaCore
|
import DeltaCore
|
||||||
|
|
||||||
|
import Roxas
|
||||||
|
|
||||||
|
extension LoadControllerSkinImageOperation
|
||||||
|
{
|
||||||
|
enum Error: Swift.Error
|
||||||
|
{
|
||||||
|
case doesNotExist
|
||||||
|
case unsupportedTraits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ControllerSkinImageCacheKey: NSObject
|
class ControllerSkinImageCacheKey: NSObject
|
||||||
{
|
{
|
||||||
let controllerSkin: ControllerSkin
|
let controllerSkin: ControllerSkin
|
||||||
@ -36,7 +47,7 @@ class ControllerSkinImageCacheKey: NSObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadControllerSkinImageOperation: LoadImageOperation<ControllerSkinImageCacheKey>
|
class LoadControllerSkinImageOperation: RSTLoadOperation<UIImage, ControllerSkinImageCacheKey>
|
||||||
{
|
{
|
||||||
let controllerSkin: ControllerSkin
|
let controllerSkin: ControllerSkin
|
||||||
let traits: DeltaCore.ControllerSkin.Traits
|
let traits: DeltaCore.ControllerSkin.Traits
|
||||||
@ -52,9 +63,23 @@ class LoadControllerSkinImageOperation: LoadImageOperation<ControllerSkinImageCa
|
|||||||
super.init(cacheKey: cacheKey)
|
super.init(cacheKey: cacheKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func loadImage() -> UIImage?
|
override func loadResult(completion: @escaping (UIImage?, Swift.Error?) -> Void)
|
||||||
{
|
{
|
||||||
let image = self.controllerSkin.image(for: self.traits, preferredSize: self.size)
|
guard self.controllerSkin.supports(self.traits) else {
|
||||||
return image
|
completion(nil, Error.unsupportedTraits)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let image = self.controllerSkin.image(for: self.traits, preferredSize: self.size) else {
|
||||||
|
completion(nil, Error.doesNotExist)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force decompression of image
|
||||||
|
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
|
||||||
|
image.draw(at: CGPoint.zero)
|
||||||
|
UIGraphicsEndImageContext()
|
||||||
|
|
||||||
|
completion(image, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// LoadImageOperation.swift
|
|
||||||
// Delta
|
|
||||||
//
|
|
||||||
// Created by Riley Testut on 2/26/16.
|
|
||||||
// Copyright © 2016 Riley Testut. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import ImageIO
|
|
||||||
|
|
||||||
import Roxas
|
|
||||||
|
|
||||||
class LoadImageOperation<CacheKeyType: AnyObject>: RSTOperation
|
|
||||||
{
|
|
||||||
var completionHandler: ((UIImage?) -> Void)? {
|
|
||||||
didSet {
|
|
||||||
self.completionBlock = {
|
|
||||||
rst_dispatch_sync_on_main_thread() {
|
|
||||||
self.completionHandler?(self.image)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var imageCache: NSCache<CacheKeyType, UIImage>? {
|
|
||||||
didSet {
|
|
||||||
// Ensures if an image is cached, it will be returned immediately, to prevent temporary flash of placeholder image
|
|
||||||
self.isImmediate = self.imageCache?.object(forKey: self.cacheKey) != nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let cacheKey: CacheKeyType
|
|
||||||
private var image: UIImage?
|
|
||||||
|
|
||||||
init(cacheKey: CacheKeyType)
|
|
||||||
{
|
|
||||||
self.cacheKey = cacheKey
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func main()
|
|
||||||
{
|
|
||||||
guard !self.isCancelled else { return }
|
|
||||||
|
|
||||||
if let cachedImage = self.imageCache?.object(forKey: self.cacheKey)
|
|
||||||
{
|
|
||||||
self.image = cachedImage
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let loadedImage = self.loadImage() else { return }
|
|
||||||
|
|
||||||
// Force decompression of image
|
|
||||||
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
|
|
||||||
loadedImage.draw(at: CGPoint.zero)
|
|
||||||
UIGraphicsEndImageContext()
|
|
||||||
|
|
||||||
self.imageCache?.setObject(loadedImage, forKey: self.cacheKey)
|
|
||||||
|
|
||||||
self.image = loadedImage
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadImage() -> UIImage?
|
|
||||||
{
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,25 +9,100 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import ImageIO
|
import ImageIO
|
||||||
|
|
||||||
|
import SDWebImage
|
||||||
|
|
||||||
import Roxas
|
import Roxas
|
||||||
|
|
||||||
class LoadImageURLOperation: LoadImageOperation<NSURL>
|
extension LoadImageURLOperation
|
||||||
{
|
{
|
||||||
public let url: URL
|
enum Error: Swift.Error
|
||||||
|
{
|
||||||
|
case doesNotExist
|
||||||
|
case invalid
|
||||||
|
case downloadFailed(Swift.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadImageURLOperation: RSTLoadOperation<UIImage, NSURL>
|
||||||
|
{
|
||||||
|
let url: URL
|
||||||
|
|
||||||
|
override var isAsynchronous: Bool {
|
||||||
|
return !self.url.isFileURL
|
||||||
|
}
|
||||||
|
|
||||||
|
private var downloadOperation: SDWebImageOperation?
|
||||||
|
|
||||||
init(url: URL)
|
init(url: URL)
|
||||||
{
|
{
|
||||||
self.url = url
|
self.url = url
|
||||||
|
|
||||||
super.init(cacheKey: url as NSURL)
|
super.init(cacheKey: url as NSURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func loadImage() -> UIImage?
|
override func cancel()
|
||||||
|
{
|
||||||
|
super.cancel()
|
||||||
|
|
||||||
|
self.downloadOperation?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func loadResult(completion: @escaping (UIImage?, Swift.Error?) -> Void)
|
||||||
|
{
|
||||||
|
let callback = { (image: UIImage?, error: Error?) in
|
||||||
|
|
||||||
|
if let image = image, !self.isCancelled
|
||||||
|
{
|
||||||
|
// Force decompression of image
|
||||||
|
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
|
||||||
|
image.draw(at: CGPoint.zero)
|
||||||
|
UIGraphicsEndImageContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(image, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.url.isFileURL
|
||||||
|
{
|
||||||
|
self.loadLocalImage(completion: callback)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.loadRemoteImage(completion: callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadLocalImage(completion: @escaping (UIImage?, Error?) -> Void)
|
||||||
{
|
{
|
||||||
let options: NSDictionary = [kCGImageSourceShouldCache as NSString: true]
|
let options: NSDictionary = [kCGImageSourceShouldCache as NSString: true]
|
||||||
|
|
||||||
guard let imageSource = CGImageSourceCreateWithURL(self.url as CFURL, options), let quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options) else { return nil }
|
guard let imageSource = CGImageSourceCreateWithURL(self.url as CFURL, options) else {
|
||||||
|
completion(nil, .doesNotExist)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options) else {
|
||||||
|
completion(nil, .invalid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let image = UIImage(cgImage: quartzImage)
|
let image = UIImage(cgImage: quartzImage)
|
||||||
return image
|
completion(image, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadRemoteImage(completion: @escaping (UIImage?, Error?) -> Void)
|
||||||
|
{
|
||||||
|
let manager = SDWebImageManager.shared()
|
||||||
|
|
||||||
|
self.downloadOperation = manager?.downloadImage(with: self.url, options: [.retryFailed, .continueInBackground], progress: nil, completed: { (image, error, cacheType, finished, imageURL) in
|
||||||
|
if let error = error
|
||||||
|
{
|
||||||
|
completion(nil, .downloadFailed(error))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completion(image, nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -236,8 +236,8 @@ private extension SaveStatesViewController
|
|||||||
if !ignoreOperations
|
if !ignoreOperations
|
||||||
{
|
{
|
||||||
let imageOperation = LoadImageURLOperation(url: saveState.imageFileURL)
|
let imageOperation = LoadImageURLOperation(url: saveState.imageFileURL)
|
||||||
imageOperation.imageCache = self.imageCache
|
imageOperation.resultsCache = self.imageCache
|
||||||
imageOperation.completionHandler = { image in
|
imageOperation.resultHandler = { (image, error) in
|
||||||
|
|
||||||
if let image = image
|
if let image = image
|
||||||
{
|
{
|
||||||
|
|||||||
@ -95,8 +95,8 @@ private extension ControllerSkinsViewController
|
|||||||
let size = UIScreen.main.defaultControllerSkinSize
|
let size = UIScreen.main.defaultControllerSkinSize
|
||||||
|
|
||||||
let imageOperation = LoadControllerSkinImageOperation(controllerSkin: controllerSkin, traits: self.traits, size: size)
|
let imageOperation = LoadControllerSkinImageOperation(controllerSkin: controllerSkin, traits: self.traits, size: size)
|
||||||
imageOperation.imageCache = self.imageCache
|
imageOperation.resultsCache = self.imageCache
|
||||||
imageOperation.completionHandler = { image in
|
imageOperation.resultHandler = { (image, error) in
|
||||||
|
|
||||||
guard let image = image else { return }
|
guard let image = image else { return }
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ extension ControllerSkinsViewController: UITableViewDataSourcePrefetching
|
|||||||
let size = UIScreen.main.defaultControllerSkinSize
|
let size = UIScreen.main.defaultControllerSkinSize
|
||||||
|
|
||||||
let imageOperation = LoadControllerSkinImageOperation(controllerSkin: controllerSkin, traits: self.traits, size: size)
|
let imageOperation = LoadControllerSkinImageOperation(controllerSkin: controllerSkin, traits: self.traits, size: size)
|
||||||
imageOperation.imageCache = self.imageCache
|
imageOperation.resultsCache = self.imageCache
|
||||||
|
|
||||||
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath as NSCopying)
|
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath as NSCopying)
|
||||||
}
|
}
|
||||||
|
|||||||
2
External/Roxas
vendored
2
External/Roxas
vendored
@ -1 +1 @@
|
|||||||
Subproject commit ecb29e0050fe9335845698c896c4cd8ce60df0da
|
Subproject commit 0057bde6337f90b5747eec1baf94a1360e78c23e
|
||||||
Loading…
Reference in New Issue
Block a user