Cache

Cache


In general, cache provides temporary storage for items that are expensive to create or load, for example via remote network calls. Because the cache has limited storage capacity, any new item added to a full cache requires an item first be removed. The cache implementation and cache replacement policy specifies which item is removed.

Caching

The Caching protocol declares the basic operations an implementer must support. The protocol is generic; the types stored in the cache are unspecified. The implementers of the cache however can specify restrictions for the types.

Default implementations of the Cache protocol provided with the SDK are: MemoryCache, SecureStoreCache, and with CompositeCache a multilevel cache.

CodableCaching

The CodableCaching protocol declares the basic operations an implementer must support. The protocol is generic; can be used with any Hashable and Equatable type as KeyType. The functions are also generic, they receive types which are conforming to Codable protocol. Implementers of the CodableCaching has to provide a coder object which should conform to CoderProtocol, and a Cache which should conform to Caching. Default implementation of the CodableCaching protocol provided with the SDK is: CodableCache.

Existing caches also can be used with the new CodableCache. The CodableCache should be initialized with a Cache conforming to Caching protocol. The cache related operations should be called on CodableCache, then the CodableCache object will encode/decode data. If the encoding/decoding is possible, the object will call the similar function of the received Cache to handle the entry.

MemoryCache

MemoryCache stores ValueType*s in memory associated with *KeyType. Currently the Least Recently Used (LRU) cache replacement policy is implemented.

    // create a memory cache with the given cache limits
   let cache = MemoryCache<String, Data>(maximumNumberOfEntries: 2, maximumCost: 0)

   let dataValue: Data = ...
   let key: String = ...
   let cost: Int = ...

   // save the value in the cache for the key associated with the cost.
   cache.set(value: dataValue, forKey: key, withCost: cost)

   // retrieves the entry for the given key
   let entry = cache.entry(forKey: key)

   //retrieves the value for the given key
   let value = cache.value(forKey: key)

   //removes all items from the cache
   cache.removeAllValues()

Using MemoryCache as part of CodableCache:

    // create codable cache with memory cache
    let cache = CodableCache(cache: MemoryCache<String, NSData>(maximumNumberOfEntries: 2, maximumCost: 0))

    let dataValue: Data = ...
    let key: String = ...
    let cost: Int = ...

    do {
        // save the value in the cache for the key associated with the cost.
        try cache.put(dataValue, for: key, with: cost)

        // retrieves the entry for the given key
        let cachedEntry = try cache.entry(Data.self, for: key)

        // retrieves the value for the given key
        let data = try cache.get(Data.self, for: key)

    } catch {
        // error handling
    }

    // removes a value from cache
    cache.remove(for: key)

    // removes all items from the cache
    cache.removeAllValues()

SecureStoreCache

SecureStoreCache stores elements in SecureStorage, with KeyType bound to String. Currently the Least Recently Used (LRU) cache replacement policy is implemented.

    let fileName: String = ...  // file name for the secure database store
    let tableName: String = ... // table name for cache
    let encryptionKey = ... // secure database store encryption key

    // create a new secure database store
    var store = SecureDatabaseStore(databaseFileName: fileName)

    // open the store using the encryption key
    try store?.open(with: encryptionKey)

    // create a secure store with the given cache limits
    let cache = SecureStoreCache<NSData>(maximumNumberOfEntries: 10, maximumCost: 5, secureStore: store!, tableName: tableName)

    let dataValue: Data = ...
    let key: String = ...
    let cost: Int = ...

    let value: NSData = NSData(data: dataValue)

    // save the value in the cache for the key associated with the cost.
    cache.set(value: value, forKey: key, withCost: cost)

    // retrieves the entry for the given key
    let entry = cache.entry(forKey: key)

    //retrieves the value for the given key
    let value = cache.value(forKey: key)

    //removes all items from the cache
    cache.removeAllValues()

Using SecureStoreCache as part of CodableCache:

    // create codable cache with secure store cache
    let store = store = SecureDatabaseStore(databaseFileName: "SampleFileName")
    let cache = SecureStoreCache<NSData>(maximumNumberOfEntries: 2, maximumCost: 10, secureStore: store, tableName: "SamleTableName")
    let codableCache = CodableCache(cache: cache)

    let dataValue: Data = ...
    let key: String = ...
    let cost: Int = ...

    do {
        // save the value in the cache for the key associated with the cost.
        try codableCache.put(dataValue, for: key, with: cost)

        // retrieves the entry for the given key
        let cachedEntry = try codableCache.entry(Data.self, for: key)

        // retrieves the value for the given key
        let data = try codableCache.get(Data.self, for: key)

    } catch {
        // error handling
    }

    // removes a value from cache
    codableCache.remove(for: key)

    // removes all items from the cache
    codableCache.removeAllValues()

CompositeCache

CompositeCache is a multi-level cache container. It stores Caching implementations which must have the same KeyType and ValueType types and use them according to a well defined rule. The caches are used in a chain: if one cache doesn’t hold the necessary data the next is queried - so the order of the caches are important. An item found in an underlying level is added to all the preceding caches. The caches are appended to the end of the chain. When a value is cleared from a cache because free space is needed to store a new value, the removed value is not added to lower level caches.

    let firstCache = MemoryCache<String, NSData>(maximumNumberOfEntries: 3, maximumCost: 0)
    let secondCache = SecureStoreCache<NSData>(maximumNumberOfEntries: 6, maximumCost: 0, secureStore: store!, tableName: tableName)

    compositeCache.addCache(firstCache)
    compositeCache.addCache(secondCache)

Using CompositeCache as part of CodableCache:

    // create codable cache with secure store cache
    let firstCache = MemoryCache<String, NSData>(maximumNumberOfEntries: 3, maximumCost: 0)
    let secondCache = SecureStoreCache<NSData>(maximumNumberOfEntries: 6, maximumCost: 0, secureStore: store!, tableName: tableName)

    let compositeCache = CompositeCache<String, NSData>()

    compositeCache.addCache(firstCache)
    compositeCache.addCache(secondCache)

    let codableCache = CodableCache(cache: compositeCache)

    let dataValue: Data = ...
    let key: String = ...
    let cost: Int = ...

    do {
        // save the value in the cache for the key associated with the cost.
        try codableCache.put(dataValue, for: key, with: cost)

        // retrieves the entry for the given key
        let cachedEntry = try codableCache.entry(Data.self, for: key)

        // retrieves the value for the given key
        let data = try codableCache.get(Data.self, for: key)

    } catch {
    // error handling
    }

    // removes a value from cache
    codableCache.remove(for: key)

    // removes all items from the cache
    codableCache.removeAllValues()

Cache component Logger ID

This component uses the following name prefix for logging: ‘SAP.Foundation.Cache’

  • CacheEntry

    CacheEntry is a simple type used by the Cache to return data to caller. This structure is not necessarily used by the cache internally to store data.

    Declaration

    Swift

    public struct CacheEntry<EntryValueType>
  • Caching

    Specifies the basic operations a cache implementation should support. In general the Cache is a key/value store. The stored items can be automatically removed from the cache when the cache reaches the maximum storage capacity. For each item in the cache a cost value can be specified. Cost is an arbitrary value (can be the size of the data for example). The behavior how the cost is handled implementation dependent. Caching is a generic protocol meaning the KeyType and ValueType can be arbitrariry selected.

    See more

    Declaration

    Swift

    public protocol Caching
  • Implementation for CodableCache Stores each instance as Data in the cache using coder for encoding/decoding. The CodableCache instance is not thread safe. Using directly from multiple threads can lead to unexpected behaviors.

    See more

    Declaration

    Swift

    open class CodableCache<Cache> : CodableCaching where Cache : Caching, Cache.ValueType == NSData
  • Protocol to support Codable protocol with Cache

    See more

    Declaration

    Swift

    public protocol CodableCaching
  • CompositeCache

    CompositeCache is a multilevel cache container. It stores Caching implementations which has to have the same KeyType and ValueType types and use them according to a well defined rule.

    let firstCache = MemoryCache<String, NSData>(maximumNumberOfEntries: 3, maximumCost: 0)
    let secondCache = SecureStoreCache<NSData>(maximumNumberOfEntries: 6, maximumCost: 0, secureStore: store!, tableName: tableName)
    
    compositeCache.addCache(firstCache)
    compositeCache.addCache(secondCache)
    

    The caches are used in a chain: if one cache doesn’t hold the necessary data the next will be queried - so the order of the caches are important. The item which was found in an underlying level will be added to all the preceding caches. The caches are appended to the end of the chain. When a value cleared from a cache because free space is needed to store a new value, the removed value won’t be added to lower level caches.

    See more

    Declaration

    Swift

    open class CompositeCache<CompositeCacheKeyType, CompositeCacheValueType> : Caching
  • MemoryCache

    MemoryCache stores ValueType*s in memory associated with *KeyType. Currently the Least Recently Used (LRU) cache replacement policy is implemented. Generic parameters:

    // create a memory cache with the given cache limits
    let cache = MemoryCache<String, Data>(maximumNumberOfEntries: 2, maximumCost: 0)
    
    let dataValue: Data = ...
    let key: String = ...
    let cost: Int = ...
    
    // save the value in the cache for the key associated with the cost.
    cache.set(value: dataValue, forKey: key, withCost: cost)
    
    // retrieves the entry for the given key
    let entry = cache.entry(forKey: key)
    
    //retrieves the value for the given key
    let value = cache.value(forKey: key)
    
    //removes all items from the cache
    cache.removeAllValues()
    
    See more

    Declaration

    Swift

    open class MemoryCache<Key, Value> : Caching where Key : Hashable

    Parameters

    Key

    the type used as a key in the cache

    Value

    the type to store in the cache

  • SecureStoreCache

    SecureStoreCache stores Strings in SecureStorage with KeyType. Currently the Least Recently Used (LRU) cache replacement policy is implemented. Generic parameters:

    let fileName: String = ...  // file name for the secure database store
    let tableName: String = ... // table name for cache
    let let encryptionKey = ... // secure database store encryption key
    
    // create a new secure database store
    var store = SecureDatabaseStore(databaseFileName: fileName)
    
    // open the store using the encryption key
    try store?.open(with: encryptionKey)
    
    // create a secure store cache with the given cache limits
    let cache = SecureStoreCache<NSData>(maximumNumberOfEntries: 10, maximumCost: 5, secureStore: store!, tableName: tableName)
    
    let dataValue: Data = ...
    let key: String = ...
    let cost: Int = ...
    
    let value: NSData = NSData(data: dataValue)
    
    // save the value in the cache for the key associated with the cost.
    cache.set(value: value, forKey: key, withCost: cost)
    
    // retrieves the entry for the given key
    let entry = cache.entry(forKey: key)
    
    //retrieves the value for the given key
    let value = cache.value(forKey: key)
    
    //removes all items from the cache
    cache.removeAllValues()
    
    See more

    Declaration

    Swift

    open class SecureStoreCache<Value> : Caching where Value : NSCoding

    Parameters

    Key

    the type used as a key in the cache

    Value

    the type to store in the cache, Note: Value implements NSCoding, see this: https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson10.html Note: SecureDatabaseStoreProtocol instance of SecureStoreCache should be stored in Library/Caches/ folder by default.