Last active
December 14, 2021 01:00
-
-
Save dbonates/79d0367a4e1940b91348e4b82bd346bb to your computer and use it in GitHub Desktop.
A tiny and still kinda work in progress Image Cache along with convenient loader class DataService
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ImageCache.swift | |
// HMTestApp | |
// | |
// Created by Daniel Bonates on 05/12/21. | |
// Modified by Daniel Bonates on 05/12/21. | |
import UIKit | |
final class ImageCache { | |
private static let appImageFolder = "images" | |
private static var cacheURL: URL { | |
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("cache") | |
} | |
static func getImage(for url: URL, completion: @escaping (UIImage?) -> ()) throws { | |
let destinationPath = cacheURL.appendingPathComponent(url.lastPathComponent) | |
if FileManager.default.fileExists(atPath: destinationPath.path) { | |
if let image = UIImage(contentsOfFile: destinationPath.path) { | |
completion(image) | |
return | |
} else { | |
throw APIError.invalidData | |
} | |
} | |
let imgResource = Resource<UIImage>(request: URLRequest(url: url), parse: { data in | |
let destinationURL = cacheURL.appendingPathComponent(url.lastPathComponent) | |
try? FileManager.default.createDirectory( | |
atPath: self.cacheURL.path, | |
withIntermediateDirectories: true, | |
attributes: [:]) | |
do { | |
try data.write(to: destinationURL) | |
} catch let error { | |
print(error.localizedDescription) | |
} | |
return UIImage(data: data) | |
}) | |
WebService.load(resource: imgResource, completion: { image in | |
completion(image) | |
}) | |
} | |
// util - clear the cache | |
static func clearCache() { | |
let fileManager = FileManager.default | |
var isDir = ObjCBool(false) | |
guard fileManager.fileExists(atPath: cacheURL.path, isDirectory: &isDir) else { | |
print("nothing to clear") | |
return | |
} | |
do { | |
let files = try fileManager.contentsOfDirectory(atPath: cacheURL.path) | |
for file in files { | |
try fileManager.removeItem(atPath: cacheURL.path + "/" + file) | |
} | |
} catch let error as NSError { | |
print("Could not clear temp folder: \(error.debugDescription)") | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ImageCache.swift | |
// Listing0 | |
// | |
// Created by Daniel Bonates on 05/03/17. | |
// Copyright © 2017 Daniel Bonates. All rights reserved. | |
// | |
import Cocoa | |
final class ImageCache { | |
private static let appImageFolder = "images" | |
private static var cacheURL: URL { | |
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("cache") | |
} | |
static func getImage(for url: URL, completion: @escaping (NSImage?) -> ()) throws { | |
let destinationPath = cacheURL.appendingPathComponent(url.lastPathComponent) | |
if FileManager.default.fileExists(atPath: destinationPath.path) { | |
if let image = NSImage(contentsOfFile: destinationPath.path) { | |
completion(image) | |
return | |
} else { | |
throw APIError.invalidData | |
} | |
} | |
let imgResource = Resource<NSImage>(request: URLRequest(url: url), parse: { data in | |
let destinationURL = cacheURL.appendingPathComponent(url.lastPathComponent) | |
try? FileManager.default.createDirectory( | |
atPath: self.cacheURL.path, | |
withIntermediateDirectories: true, | |
attributes: [:]) | |
do { | |
try data.write(to: destinationURL) | |
} catch let error { | |
print(error.localizedDescription) | |
} | |
return NSImage(data: data) | |
}) | |
WebService.load(resource: imgResource, completion: { image in | |
completion(image) | |
}) | |
} | |
// util - clear the cache | |
static func clearCache() { | |
let fileManager = FileManager.default | |
var isDir = ObjCBool(false) | |
guard fileManager.fileExists(atPath: cacheURL.path, isDirectory: &isDir) else { | |
print("nothing to clear") | |
return | |
} | |
do { | |
let files = try fileManager.contentsOfDirectory(atPath: cacheURL.path) | |
for file in files { | |
try fileManager.removeItem(atPath: cacheURL.path + "/" + file) | |
} | |
} catch let error as NSError { | |
print("Could not clear temp folder: \(error.debugDescription)") | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// WebService.swift | |
// Listing0 | |
// | |
// Created by Daniel Bonates on 05/03/17. | |
// Copyright © 2017 Daniel Bonates. All rights reserved. | |
// | |
import Foundation | |
enum APIError: Error { | |
case invalidURL | |
case invalidData | |
case invalidResponseFormat | |
case unknown | |
var errorMessage: String { | |
switch self { | |
case .invalidURL: | |
return "invalid URL" | |
case .invalidData: | |
return "no data or invalid format to decode" | |
case .invalidResponseFormat: | |
return "response format unexpected" | |
case .unknown: | |
return "network error, not known" | |
} | |
} | |
} | |
struct Resource<T> { | |
var request: URLRequest | |
var parse: (Data) -> T? | |
} | |
final class WebService { | |
static func load<T>(resource: Resource<T>, completion: @escaping (T?) -> ()) { | |
(URLSession.shared.dataTask(with: resource.request, completionHandler: { data, response, error in | |
guard error == nil else { print(error.debugDescription); return } | |
guard | |
let response = response as? HTTPURLResponse, | |
response.statusCode == 200 | |
else { | |
print("request failed.") | |
return | |
} | |
guard let data = data else { completion(nil); return } | |
completion(resource.parse(data)) | |
})).resume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TODO: this cache system could be upgraded and work as storage for any type. For download videos for offline viewing, for example. This could be accomplished by implementing a
justDownload
kind of function, with a Bool to return the status of the operation.