Allows to store values in memory, powered by system NSCache (but for value types too).
The Cache
class is full based in a John Sundell tutorial (check out at See Also section).
Also, there's a Environment modifier to allow share cache between views in same context. It would be helpful in situations where Cache is initialized just once in runtime.
And remember, Cache
is only cache-memory, so use it wisely.
For file cache based, I trully recommend reading the article mentioned at See Also to understand and implement file-based cache.
Since it brings more complexibility and enable more issues, I'm only dealing with memory in this one to keep things more simple.
Notice in the example below, cache should be provided at initialization. This allows to share cache outside the Loader and enables easy unit testing.
final class SomeDataLoader {
private let cache: Cache<URL, [SomeModel]>
private let queue = DispatchQueue(label: "com.myapp.AppName:SomeDataLoader.queue")
private let session: URLSession
init(withSession session: URLSession = .shared, cache: Cache<URL, [SomeModel]> = .init()) {
self.session = session
self.cache = cache
}
func load(fromURL url: URL) -> AnyPublisher<[SomeModel], Error> {
// first, try to obtain the current url from the cache
if let cached = cache[url] {
return Just<[SomeModel]>(cached)
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
// otherwhise, perform the networking operation
return session
.dataTaskPublisher(for: url)
.map(\.data)
.decode(type: [SomeModel].self, decoder: JSONDecoder())
.receive(on: queue)
// this is a side-effect that stores the obtained value in cache
.handleEvents(receiveOutput: { [weak self] articles in
self?.cache.set(articles, forKey: url)
})
.share()
.eraseToAnyPublisher()
}
}
Caching in Swift is the article that Cache
was full inspired, (mostly a copy with a few improvements).
MIT