A lightweight caching and data retrieval library for iOS which aims to be as non-intrusive as possible. To see example usage of EZCache check out the sample project repository.
The original aim of the project was to understand when and where to use generics in software engineering. Swift, being a language that favors strongly typed software patterns, was perfect for this. Further understanding was achieved through the implementation of generic protocols with associated types and inferred generic typing with multiple layers of abstraction for different types of caching.
Implement Cacheable on the struct or class you want to cache. If your object conforms to Codable it's really simple to get started.
extension YourData: Cacheable { }Instantiate a DataFetcher on an object that won't be deallocated during use such as a UIViewController or a view model layer. If the DataFetcher or its parent is deallocated the underlying Cache will be invalidated and emptied.
let dataFetcher = DataFetcher<YourData>()Provide a URL with some data that conforms to your data type whether it be image data or JSON. If this operation has previously been successful for the specified URL during the lifecycle of the DataFetcher then it will retrieve it from the cache. If the DataFetcher is new or the app was terminated then it will attempt to retrieve it from local storage instead.
self.dataFetcher.fetch(from: URL("http://www.myurl.com/data")!) { (result) in
switch result {
case .success(let yourData):
// Do something with your data
break
case .failure(let error):
break
}
}...and that's pretty much it! There are a few other things you can customise and fine tune using Cacheable which you'll need to do if you want to decode more elaborate data such as an image, PDF or another file format. Here's an example of a more precise implementation of Cacheable from the CacheableImage struct:
extension CacheableImage: Cacheable {
public static var subdirectoryName: String { return "images" }
public static var fileExtension: String { return ".png" }
public static var storagePolicy: StoragePolicy { return .allowStale }
public static func decode(from data: Data) throws -> CacheableImage {
guard let image = UIImage(data: data) else { throw CachingError.decodingFailed }
return CacheableImage(image)
}
public func toData() throws -> Data? {
return self.rawValue.pngData()
}
}- Provide real error handling
- Introduce
StoragePolicyto allow state data refreshing or ignorance - Streamline
Cacheableimplementation by providing default values and functions - Change any remaining synchronous calls into asynchronous or provide both
- Allow
DataFetcherto be constructed with a passedCacheinstance, but default to a shared singleton instance if none is provided - Introduce
UIImageViewhelper or subclass for making network calls even simpler - Tidy up code
- Provide useful comments