mirror of
https://github.com/samsonjs/CacheCreek.git
synced 2026-03-25 09:05:53 +00:00
Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 506d197a31 | |||
| 9f38497427 | |||
| 45538b940c |
8 changed files with 112 additions and 89 deletions
|
|
@ -211,16 +211,18 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0720;
|
LastSwiftUpdateCheck = 0720;
|
||||||
LastUpgradeCheck = 0730;
|
LastUpgradeCheck = 0800;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
30D75C221C57CE1400F4E62D = {
|
30D75C221C57CE1400F4E62D = {
|
||||||
CreatedOnToolsVersion = 7.2;
|
CreatedOnToolsVersion = 7.2;
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
};
|
};
|
||||||
30D75C331C57D17400F4E62D = {
|
30D75C331C57D17400F4E62D = {
|
||||||
CreatedOnToolsVersion = 7.2;
|
CreatedOnToolsVersion = 7.2;
|
||||||
};
|
};
|
||||||
30D75C401C57D2CA00F4E62D = {
|
30D75C401C57D2CA00F4E62D = {
|
||||||
CreatedOnToolsVersion = 7.2;
|
CreatedOnToolsVersion = 7.2;
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -310,7 +312,24 @@
|
||||||
30D75C1C1C57CD6100F4E62D /* Debug */ = {
|
30D75C1C1C57CD6100F4E62D /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
|
@ -318,6 +337,24 @@
|
||||||
30D75C1D1C57CD6100F4E62D /* Release */ = {
|
30D75C1D1C57CD6100F4E62D /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|
@ -338,7 +375,7 @@
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
|
@ -373,6 +410,7 @@
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
VERSION_INFO_PREFIX = "";
|
VERSION_INFO_PREFIX = "";
|
||||||
|
|
@ -396,7 +434,7 @@
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
|
@ -423,6 +461,7 @@
|
||||||
PRODUCT_NAME = CacheCreek;
|
PRODUCT_NAME = CacheCreek;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
|
@ -447,6 +486,7 @@
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
|
@ -504,6 +544,7 @@
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
|
@ -582,6 +623,7 @@
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
|
@ -622,6 +664,7 @@
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuudles.CacheCreekTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.nuudles.CacheCreekTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0730"
|
LastUpgradeVersion = "0800"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0730"
|
LastUpgradeVersion = "0800"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|
|
||||||
|
|
@ -54,41 +54,41 @@ class CacheCreekTests: XCTestCase {
|
||||||
|
|
||||||
let floatKey: Float = 123.456
|
let floatKey: Float = 123.456
|
||||||
cache.set(item: 123.456, forKey: floatKey)
|
cache.set(item: 123.456, forKey: floatKey)
|
||||||
XCTAssert(cache.item(forKey: floatKey) as Double? == .Some(123.456))
|
XCTAssert(cache.item(forKey: floatKey) as Double? == .some(123.456))
|
||||||
|
|
||||||
cache[floatKey] = 456.789
|
cache[floatKey] = 456.789
|
||||||
XCTAssert(cache.count == 1)
|
XCTAssert(cache.count == 1)
|
||||||
XCTAssert(cache[floatKey] as? Double == .Some(456.789))
|
XCTAssert(cache[floatKey] as? Double == .some(456.789))
|
||||||
|
|
||||||
cache.set(item: "123.456", forKey: "123.456")
|
cache.set(item: "123.456", forKey: "123.456")
|
||||||
XCTAssert(cache.count == 2)
|
XCTAssert(cache.count == 2)
|
||||||
XCTAssert(cache.item(forKey: "123.456") as String? == .Some("123.456"))
|
XCTAssert(cache.item(forKey: "123.456") as String? == .some("123.456"))
|
||||||
|
|
||||||
let boolKey = true
|
let boolKey = true
|
||||||
cache.set(item: true, forKey: boolKey)
|
cache.set(item: true, forKey: boolKey)
|
||||||
XCTAssert(cache.count == 3)
|
XCTAssert(cache.count == 3)
|
||||||
XCTAssert(cache.item(forKey: boolKey) as Bool? == .Some(true))
|
XCTAssert(cache.item(forKey: boolKey) as Bool? == .some(true))
|
||||||
|
|
||||||
cache.removeItem(forKey: boolKey)
|
cache.removeItem(forKey: boolKey)
|
||||||
XCTAssert(cache.count == 2)
|
XCTAssert(cache.count == 2)
|
||||||
XCTAssert(cache.item(forKey: boolKey) as Bool? == .None)
|
XCTAssert(cache.item(forKey: boolKey) as Bool? == .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSettingAndGettingEnum() {
|
func testSettingAndGettingEnum() {
|
||||||
let cache = LRUCache()
|
let cache = LRUCache()
|
||||||
cache["ABC"] = TestEnum.ABC
|
cache["ABC"] = TestEnum.abc
|
||||||
cache["DEF"] = TestEnum.DEF("BlahBlahBlah")
|
cache["DEF"] = TestEnum.def("BlahBlahBlah")
|
||||||
cache["GHI"] = TestEnum.GHI(-500)
|
cache["GHI"] = TestEnum.ghi(-500)
|
||||||
|
|
||||||
guard let abc: TestEnum = cache.item(forKey: "ABC"),
|
guard let abc: TestEnum = cache.item(forKey: "ABC"),
|
||||||
def: TestEnum = cache.item(forKey: "DEF"),
|
let def: TestEnum = cache.item(forKey: "DEF"),
|
||||||
ghi: TestEnum = cache.item(forKey: "GHI")
|
let ghi: TestEnum = cache.item(forKey: "GHI")
|
||||||
else {
|
else {
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch (abc, def, ghi) {
|
switch (abc, def, ghi) {
|
||||||
case (.ABC, .DEF(let stringValue), .GHI(let intValue)):
|
case (.abc, .def(let stringValue), .ghi(let intValue)):
|
||||||
XCTAssert(stringValue == "BlahBlahBlah")
|
XCTAssert(stringValue == "BlahBlahBlah")
|
||||||
XCTAssert(intValue == -500)
|
XCTAssert(intValue == -500)
|
||||||
default:
|
default:
|
||||||
|
|
@ -101,30 +101,30 @@ class CacheCreekTests: XCTestCase {
|
||||||
|
|
||||||
// Int subscript
|
// Int subscript
|
||||||
cache[123] = 123
|
cache[123] = 123
|
||||||
XCTAssert(cache[123] as? Int == .Some(123))
|
XCTAssert(cache[123] as? Int == .some(123))
|
||||||
XCTAssert(cache.count == 1)
|
XCTAssert(cache.count == 1)
|
||||||
|
|
||||||
cache[123] = nil
|
cache[123] = nil
|
||||||
XCTAssert(cache[123] as? Int == .None)
|
XCTAssert(cache[123] as? Int == .none)
|
||||||
XCTAssert(cache.count == 0)
|
XCTAssert(cache.count == 0)
|
||||||
|
|
||||||
// String subscript
|
// String subscript
|
||||||
cache["123"] = 123
|
cache["123"] = 123
|
||||||
XCTAssert(cache["123"] as? Int == .Some(123))
|
XCTAssert(cache["123"] as? Int == .some(123))
|
||||||
XCTAssert(cache.count == 1)
|
XCTAssert(cache.count == 1)
|
||||||
|
|
||||||
cache["123"] = nil
|
cache["123"] = nil
|
||||||
XCTAssert(cache["123"] as? Int == .None)
|
XCTAssert(cache["123"] as? Int == .none)
|
||||||
XCTAssert(cache.count == 0)
|
XCTAssert(cache.count == 0)
|
||||||
|
|
||||||
// Float subscript
|
// Float subscript
|
||||||
let floatKey: Float = 3.14
|
let floatKey: Float = 3.14
|
||||||
cache[floatKey] = 123
|
cache[floatKey] = 123
|
||||||
XCTAssert(cache[floatKey] as? Int == .Some(123))
|
XCTAssert(cache[floatKey] as? Int == .some(123))
|
||||||
XCTAssert(cache.count == 1)
|
XCTAssert(cache.count == 1)
|
||||||
|
|
||||||
cache[floatKey] = nil
|
cache[floatKey] = nil
|
||||||
XCTAssert(cache[floatKey] as? Int == .None)
|
XCTAssert(cache[floatKey] as? Int == .none)
|
||||||
XCTAssert(cache.count == 0)
|
XCTAssert(cache.count == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ class CacheCreekTests: XCTestCase {
|
||||||
|
|
||||||
XCTAssert(cache.count == 4)
|
XCTAssert(cache.count == 4)
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationDidReceiveMemoryWarningNotification, object: UIApplication.sharedApplication())
|
NotificationCenter.default.post(name: NSNotification.Name.UIApplicationDidReceiveMemoryWarning, object: UIApplication.shared)
|
||||||
|
|
||||||
XCTAssert(cache.count == 0)
|
XCTAssert(cache.count == 0)
|
||||||
|
|
||||||
|
|
@ -169,7 +169,7 @@ class CacheCreekTests: XCTestCase {
|
||||||
|
|
||||||
XCTAssert(cache.count == 4)
|
XCTAssert(cache.count == 4)
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationDidEnterBackgroundNotification, object: UIApplication.sharedApplication())
|
NotificationCenter.default.post(name: NSNotification.Name.UIApplicationDidEnterBackground, object: UIApplication.shared)
|
||||||
|
|
||||||
XCTAssert(cache.count == 0)
|
XCTAssert(cache.count == 0)
|
||||||
|
|
||||||
|
|
@ -238,13 +238,14 @@ class CacheCreekTests: XCTestCase {
|
||||||
func testObjCObjects() {
|
func testObjCObjects() {
|
||||||
let cache = LRUCache()
|
let cache = LRUCache()
|
||||||
|
|
||||||
let oldCache = NSCache()
|
let boxedInt = NSNumber(value: 42)
|
||||||
cache.set(item: oldCache, forKey: "InceptionCache")
|
cache.set(item: boxedInt, forKey: "Answer")
|
||||||
|
|
||||||
guard let _: NSCache = cache.item(forKey: "InceptionCache") else {
|
guard let answer: NSNumber = cache.item(forKey: "Answer") else {
|
||||||
XCTFail("Expected an NSCache object")
|
XCTFail("Expected an NSNumber object")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
XCTAssert(answer.intValue == 42)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +255,7 @@ private struct TestStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum TestEnum {
|
private enum TestEnum {
|
||||||
case ABC
|
case abc
|
||||||
case DEF(String)
|
case def(String)
|
||||||
case GHI(Int)
|
case ghi(Int)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
README.md
28
README.md
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
`CacheCreek` provides an an LRU cache that allows you to store any item, including objects, pure Swift structs, enums (with associated values), etc. Simply put, it's designed to act like an `NSCache` for everything, including Swift variables.
|
`CacheCreek` provides an an LRU cache that allows you to store any item, including objects, pure Swift structs, enums (with associated values), etc. Simply put, it's designed to act like an `NSCache` for everything, including Swift variables.
|
||||||
|
|
||||||
|
]  [](https://sjs.mit-license.org)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Simply set, get, and remove items based on any key that is `Hashable`
|
- Simply set, get, and remove items based on any key that is `Hashable`
|
||||||
|
|
@ -19,28 +21,6 @@
|
||||||
- tvOS 9.0+
|
- tvOS 9.0+
|
||||||
- Xcode 7+
|
- Xcode 7+
|
||||||
|
|
||||||
## Installation using CocoaPods
|
|
||||||
|
|
||||||
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects.
|
|
||||||
|
|
||||||
Because `CacheCreek` is written in Swift, you must use frameworks.
|
|
||||||
|
|
||||||
To integrate `CacheCreek` into your Xcode project using CocoaPods, specify it in your `Podfile`:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
source 'https://github.com/CocoaPods/Specs.git'
|
|
||||||
platform :ios, '8.0'
|
|
||||||
use_frameworks!
|
|
||||||
|
|
||||||
pod 'CacheCreek'
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, run the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pod install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation using Carthage
|
## Installation using Carthage
|
||||||
|
|
||||||
Add this to your `Cartfile`:
|
Add this to your `Cartfile`:
|
||||||
|
|
@ -93,4 +73,6 @@ print("\(cache.count)") // shows a count of 2
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
[MIT License](https://sjs.mit-license.org)
|
Copyright (c) 2015 Christopher Luu [MIT License](https://github.com/nuudles/CacheIsKing/blob/f93527d8ccc3f88b2e0697e9fd78be28d40a3a26/LICENSE)
|
||||||
|
|
||||||
|
Copyright © 2016 Sami Samhuri [MIT License](https://sjs.mit-license.org)
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ import Foundation
|
||||||
/// `AnyKey` is a simple struct that conforms to `Hashable` to allow any other `Hashable` key to be used in the cache dictionary
|
/// `AnyKey` is a simple struct that conforms to `Hashable` to allow any other `Hashable` key to be used in the cache dictionary
|
||||||
struct AnyKey: Hashable {
|
struct AnyKey: Hashable {
|
||||||
/// The underlying value
|
/// The underlying value
|
||||||
private let underlying: Any
|
fileprivate let underlying: Any
|
||||||
/// The hashing function
|
/// The hashing function
|
||||||
private let hashValueFunc: () -> Int
|
fileprivate let hashValueFunc: () -> Int
|
||||||
/// The equality function
|
/// The equality function
|
||||||
private let equalityFunc: (Any) -> Bool
|
fileprivate let equalityFunc: (Any) -> Bool
|
||||||
|
|
||||||
init<T: Hashable>(_ key: T) {
|
init<T: Hashable>(_ key: T) {
|
||||||
underlying = key
|
underlying = key
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,17 @@ struct DoublyLinkedList {
|
||||||
|
|
||||||
typealias Node = DoublyLinkedListNode
|
typealias Node = DoublyLinkedListNode
|
||||||
|
|
||||||
private(set) var head: Node?
|
fileprivate(set) var head: Node?
|
||||||
|
|
||||||
private(set) var tail: Node?
|
fileprivate(set) var tail: Node?
|
||||||
|
|
||||||
private(set) var count = 0
|
fileprivate(set) var count = 0
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
return head == nil
|
return head == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func prepend(key key: AnyKey, value: Any) -> Node {
|
mutating func prepend(key: AnyKey, value: Any) -> Node {
|
||||||
let node = Node(key: key, value: value)
|
let node = Node(key: key, value: value)
|
||||||
node.next = head
|
node.next = head
|
||||||
head?.prev = node
|
head?.prev = node
|
||||||
|
|
@ -31,7 +31,7 @@ struct DoublyLinkedList {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func append(key key: AnyKey, value: Any) -> Node {
|
mutating func append(key: AnyKey, value: Any) -> Node {
|
||||||
let node = Node(key: key, value: value)
|
let node = Node(key: key, value: value)
|
||||||
node.prev = tail
|
node.prev = tail
|
||||||
tail?.next = node
|
tail?.next = node
|
||||||
|
|
@ -57,27 +57,24 @@ struct DoublyLinkedList {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func remove(node node: Node) {
|
mutating func remove(node: Node) {
|
||||||
if let prev = node.prev {
|
if node === head {
|
||||||
prev.next = node.next
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
head = node.next
|
head = node.next
|
||||||
}
|
}
|
||||||
if let next = node.next {
|
if node === tail {
|
||||||
next.prev = node.prev
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tail = node.prev
|
tail = node.prev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.prev?.next = node.next
|
||||||
|
node.next?.prev = node.prev
|
||||||
node.next = nil
|
node.next = nil
|
||||||
node.prev = nil
|
node.prev = nil
|
||||||
count -= 1
|
count -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func moveToHead(node node: Node) {
|
mutating func moveToHead(node: Node) {
|
||||||
remove(node: node)
|
remove(node: node)
|
||||||
prepend(key: node.key, value: node.value)
|
let _ = prepend(key: node.key, value: node.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,21 @@
|
||||||
// Modified to use LRU eviction by Sami Samhuri on 2016-08-10.
|
// Modified to use LRU eviction by Sami Samhuri on 2016-08-10.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import UIKit
|
||||||
|
|
||||||
/// `LRUCache` is an LRU cache that can hold anything, including Swift structs, enums, and values.
|
/// `LRUCache` is an LRU cache that can hold anything, including Swift structs, enums, and values.
|
||||||
/// It is designed to work similar to the `NSCache`, but with native Swift support.
|
/// It is designed to work similar to the `NSCache`, but with native Swift support.
|
||||||
///
|
///
|
||||||
public class LRUCache {
|
public final class LRUCache {
|
||||||
// MARK: - Private variables
|
// MARK: - Private variables
|
||||||
/// An array of `NSNotificationCenter` observers that need to be removed upon deinitialization
|
/// An array of `NSNotificationCenter` observers that need to be removed upon deinitialization
|
||||||
private var notificationObservers: [NSObjectProtocol] = []
|
fileprivate var notificationObservers: [NSObjectProtocol] = []
|
||||||
|
|
||||||
/// The list of cached items. Most recently used item at head, least recently used item at tail.
|
/// The list of cached items. Most recently used item at head, least recently used item at tail.
|
||||||
private var items: DoublyLinkedList = DoublyLinkedList()
|
fileprivate var items: DoublyLinkedList = DoublyLinkedList()
|
||||||
|
|
||||||
/// Maps keys of cached items to nodes in the linked list.
|
/// Maps keys of cached items to nodes in the linked list.
|
||||||
private var keyToNodeMap: [AnyKey:DoublyLinkedListNode] = [:]
|
fileprivate var keyToNodeMap: [AnyKey:DoublyLinkedListNode] = [:]
|
||||||
|
|
||||||
// MARK: - Public variables
|
// MARK: - Public variables
|
||||||
/// The number of items in the cache.
|
/// The number of items in the cache.
|
||||||
|
|
@ -39,27 +39,27 @@ public class LRUCache {
|
||||||
|
|
||||||
// MARK: - Initialization methods
|
// MARK: - Initialization methods
|
||||||
public init() {
|
public init() {
|
||||||
let removalBlock = { [unowned self] (_: NSNotification) in
|
let removalBlock = { [unowned self] (_: Notification) in
|
||||||
self.removeAllItems()
|
self.removeAllItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
var notificationObserver = NSNotificationCenter.defaultCenter()
|
var notificationObserver = NotificationCenter.default
|
||||||
.addObserverForName(UIApplicationDidReceiveMemoryWarningNotification,
|
.addObserver(forName: NSNotification.Name.UIApplicationDidReceiveMemoryWarning,
|
||||||
object: UIApplication.sharedApplication(),
|
object: UIApplication.shared,
|
||||||
queue: nil,
|
queue: nil,
|
||||||
usingBlock: removalBlock)
|
using: removalBlock)
|
||||||
notificationObservers.append(notificationObserver)
|
notificationObservers.append(notificationObserver)
|
||||||
notificationObserver = NSNotificationCenter.defaultCenter()
|
notificationObserver = NotificationCenter.default
|
||||||
.addObserverForName(UIApplicationDidEnterBackgroundNotification,
|
.addObserver(forName: NSNotification.Name.UIApplicationDidEnterBackground,
|
||||||
object: UIApplication.sharedApplication(),
|
object: UIApplication.shared,
|
||||||
queue: nil,
|
queue: nil,
|
||||||
usingBlock: removalBlock)
|
using: removalBlock)
|
||||||
notificationObservers.append(notificationObserver)
|
notificationObservers.append(notificationObserver)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
notificationObservers.forEach {
|
notificationObservers.forEach {
|
||||||
NSNotificationCenter.defaultCenter().removeObserver($0)
|
NotificationCenter.default.removeObserver($0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ public class LRUCache {
|
||||||
/// - parameter item: The item to be cached
|
/// - parameter item: The item to be cached
|
||||||
/// - parameter key: The key with which to cache the item
|
/// - parameter key: The key with which to cache the item
|
||||||
///
|
///
|
||||||
public func set<K: Hashable>(item item: Any, forKey key: K) {
|
public func set<K: Hashable>(item: Any, forKey key: K) {
|
||||||
let key = AnyKey(key)
|
let key = AnyKey(key)
|
||||||
if let existingNode = keyToNodeMap[key] {
|
if let existingNode = keyToNodeMap[key] {
|
||||||
items.remove(node: existingNode)
|
items.remove(node: existingNode)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue