Awesome Cache Delightful on-disk cache (written in Swift). Backed by NSCache for maximum performance

Overview

Awesome Cache

Build Status CocoaPods Compatible Carthage compatible Swift 3.0 Platform

Delightful on-disk cache (written in Swift). Backed by NSCache for maximum performance and support for expiry of single objects.

Usage

do {
    let cache = try Cache<NSString>(name: "awesomeCache")

    cache["name"] = "Alex"
    let name = cache["name"]
    cache["name"] = nil
} catch _ {
    print("Something went wrong :(")
}

Sync by design

AwesomeCache >= 3.0 is designed to have a sync API, making it easy to reason about the actual contents of the cache. This decision has been made based on feedback from the community, to keep the API of AwesomeCache small and easy to use.

The internals of the cache use a concurrent dispatch queue, that syncs reads and writes for thread safety. In case a particular caching operation blocks your main thread for too long, consider offloading the read and write operations to a different thread.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
	cache["name"] = "Alex"
}

Cache expiry

Objects can also be cached for a certain period of time.

cache.setObject("Alex", forKey: "name", expires: .never) // same as cache["name"] = "Alex"
cache.setObject("Alex", forKey: "name", expires: .seconds(2)) // name expires in 2 seconds
cache.setObject("Alex", forKey: "name", expires: .date(Date(timeIntervalSince1970: 1428364800))) // name expires on 4th of July 2015

If an object is accessed after its expiry date, it is automatically removed from the cache and deleted from disk. However, you are responsible to delete expired objects regularly by calling removeExpiredObjects (e.g. on app launch).

Awesome API Caching

API responses are usually cached for a specific period of time. AwesomeCache provides an easy method to cache a block of asynchronous tasks.

cache.setObject(forKey: "name", cacheBlock: { success, failure in
  // Perform tasks, e.g. call an API
  let response = ...

  success(response, .seconds(300)) // Cache response for 5 minutes
  // ... or failure(error)
}, completion: { object, isLoadedFromCache, error in
	if object {
	 	// object is now cached
	}
})

If the cache already contains an object, the completion block is called with the cached object immediately.

If no object is found or the cached object is already expired, the cacheBlock is called. You may perform any tasks (e.g. network calls) within this block. Upon completion of these tasks, make sure to call the success or failure block that is passed to the cacheBlock. The cacheBlock will not be re-evaluated until the object is expired or manually deleted.

The completion block is invoked as soon as the cacheBlock is finished and the object is cached.

Version Compatibility

Current Swift compatibility breakdown:

Swift Version Framework Version
3.0 5.x
2.3 4.x
2.2 3.x

Installation

Carthage

Add the following line to your Cartfile.

github "aschuch/AwesomeCache"

Then run carthage update.

CocoaPods

Add the following line to your Podfile.

3.0" ">
pod "AwesomeCache", "~> 3.0"

Then run pod install with CocoaPods 0.36 or newer.

Manually

Just drag and drop the two .swift files as well as the NSKeyedUnarchiverWrapper.h/.m files in the AwesomeCache folder into your project. If you are adding AwesomeCache to a Swift project, you also need to add an import for NSKeyedUnarchiverWrapper.h to your bridging header.

Tests

Open the Xcode project and press ⌘-U to run the tests.

Alternatively, all tests can be run in the terminal using xctool.

xctool -scheme AwesomeCacheTests -sdk iphonesimulator test

Contributing

  • Create something awesome, make the code better, add some functionality, whatever (this is the hardest part).
  • Fork it
  • Create new branch to make your changes
  • Commit all your changes to your branch
  • Submit a pull request

Contact

Feel free to get in touch.

Comments
  • Not working with Swift 3.0

    Not working with Swift 3.0

    Not compiling with the Swift 3.0. I used Xcode 8.0 default migration tool to convert in Swift 3.0 but still no luck. Please find below error image for reference.

    swift3 0_error
    opened by mobitronics 10
  • Remove object synchronously

    Remove object synchronously

    I think it's good if we have an option to remove/clear objects synchronously. The scenario is that i know the cache is no longer valid and i want to make sure that i don't fetch from it until i completely remove all objects.

    enhancement 
    opened by namanhams 8
  • Permission on cache files

    Permission on cache files

    Hi, thanks for making AwesomeCache - I really like it. :-)

    But, I'm having a number of crashes, and they are almost always related to writing or reading files. My hypothesis is that the user has locked his or her device, and the device requires a passcode or touch id to unlock. The default now would be that access to files for threads running in the background is locked. I do background fetch, grab some data of the network, and cache the parts I need. During the operation, I also look up items from the cache. When it hits the disk, and reads or writes them from there, what permissions do they have? Can I set them myself? Perhaps on a cache-by-cache level? For these caches, the data isn't sensitive at all, so I can grant them full read/write / no security.

    Cheers

    Nik

    opened by niklassaers 5
  • Huge cache size

    Huge cache size

    We are using AwesomeCache and it's great.

    Now I implemented it for some bigger images and suddenly noticed a crazy amount of disk usage.

    A picture with 414kb takes up almost 5MB on disk (Caches/com.aschuch.cache/images/xxx.cache). Is this something expected?

    Help would be much appreciated!

    opened by MattesGroeger 5
  • Unresolved Identifier in Cache.swift File

    Unresolved Identifier in Cache.swift File

    Hello, I installed AwesomeCache into my Xcode project through the manual installation method; however, when I attempt to run my program, there is an error in the Cache.swift file that says " Use of unresolved identifier '_awesomeCache_unarchiveObjectSafely' " (Line 235 in the file). Is there a fix for this or is this possibly an issue that resulted from using the manual installation? Thanks!

    opened by jdulb17 4
  • AwesomeCache does not build Swift 1.2 as default.

    AwesomeCache does not build Swift 1.2 as default.

    I just inserted

    github "aschuch/AwesomeCache" 
    

    into my Cartfile and did a carthage update. Carthage did not installed the current master as default but the last tagged Version which is the Swift 1.1 Tag.

    *** Checking out AwesomeCache at "swift-1.1"
    

    changing the Cartfile to

    github "aschuch/AwesomeCache" "master"
    

    checked out the master branch.

    And the Swift-1.1 tag does not build at my environment at all. I get the following error messages:

    2015-06-03 10:04:31.213 xcodebuild[3478:43851] [MT] PluginLoading: Required plug-in compatibility UUID E969541F-E6F9-4D25-8158-72DC3545A6C6 for plug-in at path 'Patoh to Xcode.xcplugin' not present in DVTPlugInCompatibilityUUIDs
    
    opened by pfitz 4
  • Implemented dictionary functions

    Implemented dictionary functions

    I'm currently developing an app, where I use a separate cache for debug information. This cache only holds debug information, if the app crashes the contents of the cache is uploaded to a backend server for analysis. Currently there is no other way to iterate over the contents of the cache.

    opened by functionaldude 3
  • Cache is empty when application quit and run background

    Cache is empty when application quit and run background

    Hi ! I have a class "CacheUtilities" i use it for stock a Static Cache of UIImage. I have a lot of image to load from my server, so i want load it just one time and keep it on my Cache (except if user close the process of my app ! )

    But i have a problem, when the user only close my app (not kill the app, just quit and make it run in background) and come back, my Cache is empty and i need to reload all images... What's the solution ?

    I use the expires .Never

    CacheUtilities.getCacheImage().setObject(UIImage(data: data)!, forKey: sUrl, expires: CacheExpiry.Never)

    opened by Persilos 3
  • add isOnMemory (recreated)

    add isOnMemory (recreated)

    Add a way to check whether a cache is on memory for a specific key. I wanna do things likes below.

    1. Check whether a cache is on memory for a specific key.
    2. If it is on memory, do 'object(forKey:)' synchronously, because it is guaranteed that object will be returned instantly.
    3. If not on memory, create a thread and operate 'object(forKey:)' asynchronously. it is because 'object(forKey:)' has to access a disk and takes longer time to return the value than when the cache is on memory.

    Because of my application have to access hundreds of object, I need to decrease the number of threads as much as I can.

    original PR is here https://github.com/aschuch/AwesomeCache/pull/80

    opened by notohiro 2
  • How do we call "">

    How do we call "public class Cache "

    i am trying like this AwesomeCache.Cache(name: name, directory: cachePath)

    but it's throwing me an error 'NSCoding' cannot be used as a type conforming to protocol 'NSCoding' because 'NSCoding' has static requirements

    opened by mobileprogrammingAnurag 2
  • Swift 3.0

    Swift 3.0

    1. Converted to Swift 3.0 by using Xcode 8.0 beta 5
    2. Migrated to Swift 3.0
    3. Update Project Settings by Xcode recommendation
    4. Change API names for adopting to Apple API Design Guidelines
    5. turned on "Allow app extension API only" for AwesomeCache-iOS target

    I know, it's too early merging this pull request. If you have any suggestion, Please comment.

    opened by notohiro 2
  • Please put up a disclaimer that this project is abandoned

    Please put up a disclaimer that this project is abandoned

    Just spent time pulling this project just to realise it doesn't even compile. Please put up a disclaimer if you don't want to maintain it any more and don't waste people's time.

    Thank you.

    opened by intonarumori 0
  • Carthage install fails

    Carthage install fails

    *** Building scheme "AwesomeCache-iOS" in Example.xcodeproj
    Build Failed
            Task failed with exit code 65:
            /usr/bin/xcrun xcodebuild -project project/Carthage/Checkouts/AwesomeCache/Example.xcodeproj -scheme AwesomeCache-iOS -configuration Release -derivedDataPath /Users/user/Library/Caches/org.carthage.CarthageKit/DerivedData/11.3.1_11C504/AwesomeCache/5.0 -sdk iphoneos ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES archive -archivePath /var/folders/zx/vkw16gb963vbw6n8w_sgl_g40000gn/T/AwesomeCache SKIP_INSTALL=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=NO CLANG_ENABLE_CODE_COVERAGE=NO STRIP_INSTALLED_PRODUCT=NO (launched in project/Carthage/Checkouts/AwesomeCache)
    
    This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/zx/vkw16gb963vbw6n8w_sgl_g40000gn/T/carthage-xcodebuild.mnupE7.log
    
    opened by yspreen 0
  • Retain cache hits in memory when loaded from disk

    Retain cache hits in memory when loaded from disk

    Currently, if the in-memory cache is purged and on-disk cached items remain, when an item is requested from the cache, it is loaded from disk each time it's requested. This is a fix that simply places items back into the in-memory cache when they're loaded from disk.

    A test has been added.

    Open to other suggestions.

    opened by gravey 0
Releases(5.0)
  • 5.0(Nov 15, 2016)

  • 4.0(Sep 18, 2016)

  • 3.0.1(Jun 27, 2016)

  • 3.0(Jun 3, 2016)

    AwesomeCache 3 is designed to have a sync API, making it easy to reason about the actual contents of the cache. This decision has been made based on feedback from the community, to keep the API of AwesomeCache small and easy to use.

    The internals of the cache use a concurrent dispatch queue, that syncs reads and writes for thread safety. In case a particular caching operation blocks your main thread for too long, consider offloading the read and write operations to a different thread.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        cache["name"] = "Alex"
    }
    

    Further improvements

    • Added a new way to return an expired object in objectForKey: if present (#31)
    • Adds a way to set the NSFileProtectionKey value on the internal NSFileManager. This may be necessary in case you observe odd behaviour when accessing the cache in the background. (#64)
    • Adds a new method to get allObjects from the cache (optionally, expired objects may be queried as well)
    Source code(tar.gz)
    Source code(zip)
  • 2.2(May 27, 2016)

    • An Obj-C NSKeyedUnarchiver was added since it can throw exceptions which can't be caught in Swift (Thanks @JaviSoto)
    • Use a concurrent queue to allow multiple simultaneous reads from the cache. (Thanks @JaviSoto)
    Source code(tar.gz)
    Source code(zip)
  • 2.1(Mar 21, 2016)

  • 2.0(Oct 17, 2015)

  • 1.0.2(Jul 9, 2015)

    • fixes a deadlock in objectForKey (thanks @alenofx)
    • keys are now sanitized to make sure the file system is able to persist the cache object
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Mar 24, 2015)

  • 1.0(Jan 31, 2015)

  • 0.2(Jul 15, 2014)

Owner
Alexander Schuch
Swift developer. Classic Mini driver.
Alexander Schuch
LRUCache is an open-source replacement for NSCache that behaves in a predictable, debuggable way

Introduction Installation Usage Concurrency Performance Credits Introduction LRUCache is an open-source replacement for NSCache that behaves in a pred

Nick Lockwood 290 Oct 20, 2022
A type-safe swifty wrapper around NSCache.

swift-cache A type-safe swifty wrapper around NSCache. Getting Started Add swift-cache as a dependency to your project using SPM. .package(url: "https

Binary Scraping 2 Jun 3, 2022
High performance cache framework for iOS.

YYCache High performance cache framework for iOS. (It's a component of YYKit) Performance You may download and compile the latest version of sqlite an

null 2.3k Dec 16, 2022
Cache - Nothing but Cache.

Cache doesn't claim to be unique in this area, but it's not another monster library that gives you a god's power. It does nothing but caching, but it does it well. It offers a good public API with out-of-box implementations and great customization possibilities. Cache utilizes Codable in Swift 4 to perform serialization.

HyperRedink 2.7k Dec 28, 2022
Apple Asset Cache (Content Cache) Tools

AssetCacheTool A library and tool for interacting with both the local and remote asset caches. This is based on research I did a few years ago on the

Kenneth Endfinger 21 Jan 5, 2023
Delightful framework for iOS to easily persist structs, images, and data

Installation • Usage • Debugging • A Word • Documentation • Apps Using Disk • License • Contribute • Questions? Disk is a powerful and simple file man

Saoud Rizwan 3k Jan 3, 2023
CachyKit - A Caching Library is written in Swift that can cache JSON, Image, Zip or AnyObject with expiry date/TTYL and force refresh.

Nice threadsafe expirable cache management that can cache any object. Supports fetching from server, single object expire date, UIImageView loading etc.

Sadman Samee 122 Dec 28, 2022
Cachyr A typesafe key-value data cache for iOS, macOS, tvOS and watchOS written in Swift.

Cachyr A typesafe key-value data cache for iOS, macOS, tvOS and watchOS written in Swift. There already exists plenty of cache solutions, so why creat

Norsk rikskringkasting (NRK) 124 Nov 24, 2022
Carlos - A simple but flexible cache, written in Swift for iOS 13+ and WatchOS 6 apps.

Carlos A simple but flexible cache, written in Swift for iOS 13+ and WatchOS 6 apps. Breaking Changes Carlos 1.0.0 has been migrated from PiedPiper de

National Media & Tech 628 Dec 3, 2022
A lightweight generic cache for iOS written in Swift with extra love for images.

Haneke is a lightweight generic cache for iOS and tvOS written in Swift 4. It's designed to be super-simple to use. Here's how you would initalize a J

Haneke 5.2k Dec 29, 2022
SwiftyCache is a dynamic and auto-managed cache written in Swift

SwiftyCache is a dynamic and auto-managed cache written in Swift. Unlike a simple cache system, it allows you to keep some data even in different executions. Guaranteeing persistence, when desired, without increasing the time required to save or recover data.

Antonio Guerra 3 Aug 28, 2022
MemoryCache - type-safe, thread-safe memory cache class in Swift

MemoryCache is a memory cache class in swift. The MemoryCache class incorporates LRU policies, which ensure that a cache doesn’t

Yusuke Morishita 74 Nov 24, 2022
Track is a thread safe cache write by Swift. Composed of DiskCache and MemoryCache which support LRU.

Track is a thread safe cache write by Swift. Composed of DiskCache and MemoryCache which support LRU. Features Thread safe: Implement by dispatch_sema

Cheer 268 Nov 21, 2022
A simple cache that can hold anything, including Swift items

CacheIsKing CacheIsKing is a simple cache that allows you to store any item, including objects, pure Swift structs, enums (with associated values), et

Christopher Luu 13 Jan 22, 2018
Everyone tries to implement a cache at some point in their iOS app’s lifecycle, and this is ours.

Everyone tries to implement a cache at some point in their app’s lifecycle, and this is ours. This is a library that allows people to cache NSData wit

Spotify 1.2k Dec 28, 2022
UITableView cell cache that cures scroll-lags on cell instantiating

UITableView + Cache https://github.com/Kilograpp/UITableView-Cache UITableView cell cache that cures scroll-lags on a cell instantiating. Introduction

null 73 Aug 6, 2021
Fast, non-deadlocking parallel object cache for iOS, tvOS and OS X

PINCache Fast, non-deadlocking parallel object cache for iOS and OS X. PINCache is a fork of TMCache re-architected to fix issues with deadlocking cau

Pinterest 2.6k Dec 28, 2022
Cache library for videos for React Native

@lowkey/react-native-cache Cache everything Installation npm install @lowkey/react-native-cache Usage import ReactNativeCache from "@lowkey/react-nati

Max Prokopenko 1 Oct 1, 2021
CachedAsyncImage is the simplest way to add cache to your AsyncImage.

CachedAsyncImage ??️ CachedAsyncImage is AsyncImage, but with cache capabilities. Usage CachedAsyncImage has the exact same API and behavior as AsyncI

Lorenzo Fiamingo 278 Jan 5, 2023