NSCache emptied when app enters background
Think you need to ensure that objects placed in cache conform to NSDiscardableContentProtocol to have desired results. From the NSCache Class Reference:
A common data type stored in NSCache objects is an object that
implements the NSDiscardableContent protocol. Storing this type of
object in a cache has benefits, because its content can be discarded
when it is not needed anymore, thus saving memory. By default,
NSDiscardableContent objects in the cache are automatically removed
from the cache if their content is discarded, although this automatic
removal policy can be changed. If an NSDiscardableContent object is
put into the cache, the cache calls discardContentIfPossible on it
upon its removal.
Does NSCache gets automatically emptied when the app is force quitted?
Yes it does that, for some reason it instantly removes data from cache when app enters background even if there is no memory pressure. To fix this you have to tell NSCache that your data should not be discarded.
What you could do is something like:
class ImageCache: NSObject , NSDiscardableContent {
public var image: UIImage!
func beginContentAccess() -> Bool {
return true
}
func endContentAccess() {
}
func discardContentIfPossible() {
}
func isContentDiscarded() -> Bool {
return false
}
}
and then use this class in NSCache like the following:
let cache = NSCache<NSString, ImageCache>()
After that you have to set the data which you cached earlier:
let cacheImage = ImageCache()
cacheImage.image = imageDownloaded
self.cache.setObject(cacheImage, forKey: "yourCustomKey" as NSString)
And finally retrieve the data:
if let cachedVersion = cache.object(forKey: "yourCustomKey") {
youImageView.image = cachedVersion.image
}
UPDATE
This was already answered by Sharjeel Ahmad. See this link for reference.
Use a global NSCache or one per class?
It obviously depends, but I would generally vote for one cache for each type of cached object. That way, you can have different countLimit
values for each, e.g. to specify things like "keep the 50 most recently rendered thumbnails", "keep the 5 most recently downloaded large images", "keep the 10 most recently downloaded PDFs", etc.
For really computationally expensive tasks, I also employ two tier caching, NSCache
for optimal performance, and saving to a temporary/cache directory in the local file system to avoid costly download cycles while not consuming RAM.
NSCache is not evicting data
From the doc (Emphasis mine): The NSCache class incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. The system automatically carries out these policies if memory is needed by other applications. When invoked, these policies remove some items from the cache, minimizing its memory footprint.
Apple does not state that the memory will be freed on memory warning - in my experience, the cache is most often purged when the app goes to background or when you add more large elements.
Related Topics
Xcode Creates Wrong IPA Folder Structure
Swift - Add Gesture Recognizer to Object in Table Cell
Game Center Login Dialog Not Shown Again After Cancelling It for the First Time (Ios7)
How to Properly Send an Image to Cloudkit as Ckasset
Error Using Swift - Instance Member Cannot Be Used on Type 'Viewcontroller'
Swiftui Foreach Index Out of Range Error When Removing Row
App Running on iPad While Its Iphone-Only
iOS Notification When Application Is Closed
Xcode 7 Beta 6, Dyld _Nsarray0_ Crash
How to Default Uilabel Font and Size Using Swift
Objective C- Trouble Updating UI on Main Thread
A Lighter Way of Discovering Text Writing Direction
Will iOS Awake My App When I Receive Silent Push Notification(When App Is Not in Running State)
Preventing Avcapturevideopreviewlayer from Rotating, But Allow UI Layer to Rotate with Orientation