diff --git a/Pod/Pod.xcodeproj/project.pbxproj b/Pod/CacheTests.xcodeproj/project.pbxproj similarity index 59% rename from Pod/Pod.xcodeproj/project.pbxproj rename to Pod/CacheTests.xcodeproj/project.pbxproj index f31e7622..f153cb6d 100644 --- a/Pod/Pod.xcodeproj/project.pbxproj +++ b/Pod/CacheTests.xcodeproj/project.pbxproj @@ -7,28 +7,43 @@ objects = { /* Begin PBXBuildFile section */ - 14A139B41AEFC72B00AD732F /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14A139B31AEFC72B00AD732F /* Tests.swift */; }; D520D4B01BBC4770001A2A31 /* MemoryCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D520D4AF1BBC4770001A2A31 /* MemoryCache.swift */; settings = {ASSET_TAGS = (); }; }; D520D4B21BBC47A2001A2A31 /* DiskCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D520D4B11BBC47A2001A2A31 /* DiskCache.swift */; settings = {ASSET_TAGS = (); }; }; D520D4B61BBC4D0B001A2A31 /* CacheAware.swift in Sources */ = {isa = PBXBuildFile; fileRef = D520D4B51BBC4D0B001A2A31 /* CacheAware.swift */; settings = {ASSET_TAGS = (); }; }; D520D4BB1BBEB59D001A2A31 /* Cachable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D520D4BA1BBEB59D001A2A31 /* Cachable.swift */; settings = {ASSET_TAGS = (); }; }; - D5704C531BC84DAA0089F388 /* String+Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5704C521BC84DAA0089F388 /* String+Base64.swift */; settings = {ASSET_TAGS = (); }; }; + D53116851BCACF6500EBD9C0 /* CacheTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53116841BCACF6500EBD9C0 /* CacheTask.swift */; settings = {ASSET_TAGS = (); }; }; + D5704C531BC84DAA0089F388 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5704C521BC84DAA0089F388 /* String+Extensions.swift */; settings = {ASSET_TAGS = (); }; }; + D5CD0F731BCAE5F6004C0B32 /* SpecHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CD0F721BCAE5F6004C0B32 /* SpecHelper.swift */; settings = {ASSET_TAGS = (); }; }; + D5EA23661BD5BDF700FEABC3 /* DiskCacheSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA23651BD5BDF700FEABC3 /* DiskCacheSpec.swift */; settings = {ASSET_TAGS = (); }; }; + D5EA23681BD5BE1400FEABC3 /* MemoryCacheSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA23671BD5BE1400FEABC3 /* MemoryCacheSpec.swift */; settings = {ASSET_TAGS = (); }; }; + D5EA236B1BD5C21200FEABC3 /* String+ExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA236A1BD5C21200FEABC3 /* String+ExtensionsSpec.swift */; settings = {ASSET_TAGS = (); }; }; + D5EA236D1BD5C3FB00FEABC3 /* CachableSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA236C1BD5C3FB00FEABC3 /* CachableSpec.swift */; settings = {ASSET_TAGS = (); }; }; + D5EA236F1BD5D12900FEABC3 /* CacheTaskSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA236E1BD5D12900FEABC3 /* CacheTaskSpec.swift */; settings = {ASSET_TAGS = (); }; }; + FB2C6582457B37B5F79DBC36 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 894692FFFEE3D6AC1422C867 /* Pods.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 146D72AC1AB782920058798C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 146D72B11AB782920058798C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 14A139B21AEFC72B00AD732F /* Tests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Bridging-Header.h"; sourceTree = ""; }; - 14A139B31AEFC72B00AD732F /* Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 14C136511AB784B200B7B07A /* .travis.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .travis.yml; path = ../.travis.yml; sourceTree = ""; }; 14C136521AB784B200B7B07A /* CONTRIBUTING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CONTRIBUTING.md; path = ../CONTRIBUTING.md; sourceTree = ""; }; 14C136541AB784B200B7B07A /* LICENSE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = LICENSE.md; path = ../LICENSE.md; sourceTree = ""; }; 14C136551AB784B200B7B07A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; + 19690E256D6AE4D5C44048DC /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; + 2162049FAFBE0ABE9112787F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + 894692FFFEE3D6AC1422C867 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D520D4AF1BBC4770001A2A31 /* MemoryCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemoryCache.swift; sourceTree = ""; }; D520D4B11BBC47A2001A2A31 /* DiskCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiskCache.swift; sourceTree = ""; }; D520D4B51BBC4D0B001A2A31 /* CacheAware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacheAware.swift; sourceTree = ""; }; D520D4BA1BBEB59D001A2A31 /* Cachable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cachable.swift; sourceTree = ""; }; - D5704C521BC84DAA0089F388 /* String+Base64.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Base64.swift"; sourceTree = ""; }; + D53116841BCACF6500EBD9C0 /* CacheTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacheTask.swift; sourceTree = ""; }; + D5704C521BC84DAA0089F388 /* String+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; + D5CD0F721BCAE5F6004C0B32 /* SpecHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpecHelper.swift; sourceTree = ""; }; + D5EA23651BD5BDF700FEABC3 /* DiskCacheSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiskCacheSpec.swift; sourceTree = ""; }; + D5EA23671BD5BE1400FEABC3 /* MemoryCacheSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemoryCacheSpec.swift; sourceTree = ""; }; + D5EA236A1BD5C21200FEABC3 /* String+ExtensionsSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+ExtensionsSpec.swift"; sourceTree = ""; }; + D5EA236C1BD5C3FB00FEABC3 /* CachableSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachableSpec.swift; sourceTree = ""; }; + D5EA236E1BD5D12900FEABC3 /* CacheTaskSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacheTaskSpec.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -36,6 +51,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + FB2C6582457B37B5F79DBC36 /* Pods.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -49,6 +65,8 @@ 14C136501AB7849300B7B07A /* Metadata */, 146D72AF1AB782920058798C /* Tests */, 146D72941AB782920058798C /* Products */, + 1E26A788C788B43A48C8276C /* Pods */, + 19D2B296CF59F08815CE40AB /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -65,9 +83,9 @@ 146D72AF1AB782920058798C /* Tests */ = { isa = PBXGroup; children = ( + D5EA23641BD5BDE700FEABC3 /* Specs */, + D5CD0F711BCAE5DC004C0B32 /* Helpers */, 146D72B01AB782920058798C /* Supporting Files */, - 14A139B31AEFC72B00AD732F /* Tests.swift */, - 14A139B21AEFC72B00AD732F /* Tests-Bridging-Header.h */, ); path = Tests; sourceTree = ""; @@ -99,15 +117,61 @@ D520D4B11BBC47A2001A2A31 /* DiskCache.swift */, D520D4B51BBC4D0B001A2A31 /* CacheAware.swift */, D520D4BA1BBEB59D001A2A31 /* Cachable.swift */, + D53116841BCACF6500EBD9C0 /* CacheTask.swift */, ); name = Source; path = ../Source; sourceTree = ""; }; + 19D2B296CF59F08815CE40AB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 894692FFFEE3D6AC1422C867 /* Pods.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 1E26A788C788B43A48C8276C /* Pods */ = { + isa = PBXGroup; + children = ( + 19690E256D6AE4D5C44048DC /* Pods.debug.xcconfig */, + 2162049FAFBE0ABE9112787F /* Pods.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; D5704C511BC84D990089F388 /* Extensions */ = { isa = PBXGroup; children = ( - D5704C521BC84DAA0089F388 /* String+Base64.swift */, + D5704C521BC84DAA0089F388 /* String+Extensions.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + D5CD0F711BCAE5DC004C0B32 /* Helpers */ = { + isa = PBXGroup; + children = ( + D5CD0F721BCAE5F6004C0B32 /* SpecHelper.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + D5EA23641BD5BDE700FEABC3 /* Specs */ = { + isa = PBXGroup; + children = ( + D5EA23691BD5C1E600FEABC3 /* Extensions */, + D5EA23651BD5BDF700FEABC3 /* DiskCacheSpec.swift */, + D5EA23671BD5BE1400FEABC3 /* MemoryCacheSpec.swift */, + D5EA236C1BD5C3FB00FEABC3 /* CachableSpec.swift */, + D5EA236E1BD5D12900FEABC3 /* CacheTaskSpec.swift */, + ); + path = Specs; + sourceTree = ""; + }; + D5EA23691BD5C1E600FEABC3 /* Extensions */ = { + isa = PBXGroup; + children = ( + D5EA236A1BD5C21200FEABC3 /* String+ExtensionsSpec.swift */, ); path = Extensions; sourceTree = ""; @@ -119,9 +183,12 @@ isa = PBXNativeTarget; buildConfigurationList = 146D72B91AB782920058798C /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( + F925BC1FC8398D793DABD5F1 /* Check Pods Manifest.lock */, 146D72A81AB782920058798C /* Sources */, 146D72A91AB782920058798C /* Frameworks */, 146D72AA1AB782920058798C /* Resources */, + 41A5726C401436A4348A7147 /* Embed Pods Frameworks */, + 1EC9FFEA0EDF4E0EFC7ABCC0 /* Copy Pods Resources */, ); buildRules = ( ); @@ -147,7 +214,7 @@ }; }; }; - buildConfigurationList = 146D728E1AB782920058798C /* Build configuration list for PBXProject "Pod" */; + buildConfigurationList = 146D728E1AB782920058798C /* Build configuration list for PBXProject "CacheTests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -175,17 +242,71 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 1EC9FFEA0EDF4E0EFC7ABCC0 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 41A5726C401436A4348A7147 /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F925BC1FC8398D793DABD5F1 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 146D72A81AB782920058798C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D5EA236B1BD5C21200FEABC3 /* String+ExtensionsSpec.swift in Sources */, + D5EA236F1BD5D12900FEABC3 /* CacheTaskSpec.swift in Sources */, + D5EA23661BD5BDF700FEABC3 /* DiskCacheSpec.swift in Sources */, D520D4B01BBC4770001A2A31 /* MemoryCache.swift in Sources */, - D5704C531BC84DAA0089F388 /* String+Base64.swift in Sources */, + D5704C531BC84DAA0089F388 /* String+Extensions.swift in Sources */, D520D4B21BBC47A2001A2A31 /* DiskCache.swift in Sources */, D520D4BB1BBEB59D001A2A31 /* Cachable.swift in Sources */, + D5EA23681BD5BE1400FEABC3 /* MemoryCacheSpec.swift in Sources */, + D53116851BCACF6500EBD9C0 /* CacheTask.swift in Sources */, + D5EA236D1BD5C3FB00FEABC3 /* CachableSpec.swift in Sources */, D520D4B61BBC4D0B001A2A31 /* CacheAware.swift in Sources */, - 14A139B41AEFC72B00AD732F /* Tests.swift in Sources */, + D5CD0F731BCAE5F6004C0B32 /* SpecHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -271,6 +392,7 @@ }; 146D72BA1AB782920058798C /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 19690E256D6AE4D5C44048DC /* Pods.debug.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -285,13 +407,15 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Tests/Tests-Bridging-Header.h"; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 146D72BB1AB782920058798C /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 2162049FAFBE0ABE9112787F /* Pods.release.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -302,14 +426,15 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Tests/Tests-Bridging-Header.h"; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 146D728E1AB782920058798C /* Build configuration list for PBXProject "Pod" */ = { + 146D728E1AB782920058798C /* Build configuration list for PBXProject "CacheTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 146D72B41AB782920058798C /* Debug */, diff --git a/Pod/Pod.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Pod/CacheTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 51% rename from Pod/Pod.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Pod/CacheTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata index f63ae216..8c50fc8a 100644 --- a/Pod/Pod.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Pod/CacheTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:/Users/vadym/Development/hyper/ios/opensource/Cache/Pod/CacheTests.xcodeproj"> diff --git a/Pod/Pod.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Pod/CacheTests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme similarity index 90% rename from Pod/Pod.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme rename to Pod/CacheTests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index a02e2347..b14d2a0b 100644 --- a/Pod/Pod.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Pod/CacheTests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -17,7 +17,7 @@ BlueprintIdentifier = "146D72AB1AB782920058798C" BuildableName = "Tests.xctest" BlueprintName = "Tests" - ReferencedContainer = "container:Pod.xcodeproj"> + ReferencedContainer = "container:CacheTests.xcodeproj"> @@ -35,7 +35,7 @@ BlueprintIdentifier = "146D72AB1AB782920058798C" BuildableName = "Tests.xctest" BlueprintName = "Tests" - ReferencedContainer = "container:Pod.xcodeproj"> + ReferencedContainer = "container:CacheTests.xcodeproj"> @@ -45,7 +45,7 @@ BlueprintIdentifier = "146D72AB1AB782920058798C" BuildableName = "Tests.xctest" BlueprintName = "Tests" - ReferencedContainer = "container:Pod.xcodeproj"> + ReferencedContainer = "container:CacheTests.xcodeproj"> @@ -67,7 +67,7 @@ BlueprintIdentifier = "146D72AB1AB782920058798C" BuildableName = "Tests.xctest" BlueprintName = "Tests" - ReferencedContainer = "container:Pod.xcodeproj"> + ReferencedContainer = "container:CacheTests.xcodeproj"> @@ -85,7 +85,7 @@ BlueprintIdentifier = "146D72AB1AB782920058798C" BuildableName = "Tests.xctest" BlueprintName = "Tests" - ReferencedContainer = "container:Pod.xcodeproj"> + ReferencedContainer = "container:CacheTests.xcodeproj"> diff --git a/Pod/CacheTests.xcworkspace/contents.xcworkspacedata b/Pod/CacheTests.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..cf9a17b3 --- /dev/null +++ b/Pod/CacheTests.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Pod/Podfile b/Pod/Podfile index 648ccb14..2522b8fc 100644 --- a/Pod/Podfile +++ b/Pod/Podfile @@ -1,7 +1,6 @@ platform :ios, '8.0' use_frameworks! +inhibit_all_warnings! -# When using more than one target in your project -# link_with 'Demo', 'Tests' - -# pod 'Sample' +pod 'Nimble', '>= 2.0.0-rc.3' +pod 'Quick' diff --git a/Pod/Podfile.lock b/Pod/Podfile.lock new file mode 100644 index 00000000..135ceef6 --- /dev/null +++ b/Pod/Podfile.lock @@ -0,0 +1,13 @@ +PODS: + - Nimble (2.0.0) + - Quick (0.6.0) + +DEPENDENCIES: + - Nimble (>= 2.0.0-rc.3) + - Quick + +SPEC CHECKSUMS: + Nimble: 472e75466819eb8c06299233e87c694a9b51328a + Quick: 563686dbcf0ae0f9f7401ac9cd2d786ee1b7f3d7 + +COCOAPODS: 0.39.0.beta.5 diff --git a/Pod/Tests/Helpers/SpecHelper.swift b/Pod/Tests/Helpers/SpecHelper.swift new file mode 100644 index 00000000..094a1667 --- /dev/null +++ b/Pod/Tests/Helpers/SpecHelper.swift @@ -0,0 +1,11 @@ +import Foundation + +class User: Cachable { + var firstName: String + var lastName: String + + init(firstName: String, lastName: String) { + self.firstName = firstName + self.lastName = lastName + } +} diff --git a/Pod/Tests/Specs/CachableSpec.swift b/Pod/Tests/Specs/CachableSpec.swift new file mode 100644 index 00000000..29d211b1 --- /dev/null +++ b/Pod/Tests/Specs/CachableSpec.swift @@ -0,0 +1,31 @@ +import Quick +import Nimble + +class CachableSpec: QuickSpec { + + override func spec() { + describe("Cachable") { + var object = User(firstName: "John", lastName: "Snow") + + describe("#encode") { + it("returns the correct encoded object data") { + let data = withUnsafePointer(&object) { p in + NSData(bytes: p, length: sizeofValue(object)) + } + + expect(object.encode()).to(equal(data)) + } + } + + describe(".decode") { + it("returns the correct decoded object") { + let data = object.encode() + let user = User.decode(data) + + expect(object.firstName).to(equal(user.firstName)) + expect(object.lastName).to(equal(user.lastName)) + } + } + } + } +} diff --git a/Pod/Tests/Specs/CacheTaskSpec.swift b/Pod/Tests/Specs/CacheTaskSpec.swift new file mode 100644 index 00000000..56afa849 --- /dev/null +++ b/Pod/Tests/Specs/CacheTaskSpec.swift @@ -0,0 +1,24 @@ +import Quick +import Nimble + +class CacheTaskSpec: QuickSpec { + + override func spec() { + describe("CacheTask") { + + describe("#start") { + it("dispatches the block") { + let expectation = self.expectationWithDescription( + "Dispatches Block Expectation") + + let task = CacheTask(processing: { + expectation.fulfill() + }) + task.start() + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + } + } +} diff --git a/Pod/Tests/Specs/DiskCacheSpec.swift b/Pod/Tests/Specs/DiskCacheSpec.swift new file mode 100644 index 00000000..76bd7062 --- /dev/null +++ b/Pod/Tests/Specs/DiskCacheSpec.swift @@ -0,0 +1,130 @@ +import Quick +import Nimble + +class DiskCacheSpec: QuickSpec { + + override func spec() { + describe("DiskCache") { + let name = "DudeDiskCache" + let key = "youknownothing" + let object = User(firstName: "John", lastName: "Snow") + var cache: DiskCache! + let fileManager = NSFileManager() + + beforeEach { + cache = DiskCache(name: name) + } + + afterEach { + do { + try fileManager.removeItemAtPath(cache.path) + } catch {} + } + + describe("#path") { + it("returns the correct path") { + let paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, + NSSearchPathDomainMask.UserDomainMask, true) + let path = "\(paths.first!)/\(cache.prefix).\(name.capitalizedString)" + + expect(cache.path).to(equal(path)) + } + } + + describe("#maxSize") { + it("returns the default maximum size of a cache") { + expect(cache.maxSize).to(equal(0)) + } + } + + describe("#add") { + it("creates cache directory") { + let expectation = self.expectationWithDescription( + "Create Cache Directory Expectation") + + cache.add(key, object: object) { + let fileExist = fileManager.fileExistsAtPath(cache.path) + expect(fileExist).to(beTrue()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + + it("saves an object") { + let expectation = self.expectationWithDescription( + "Save Object Expectation") + + cache.add(key, object: object) { + let fileExist = fileManager.fileExistsAtPath(cache.filePath(key)) + expect(fileExist).to(beTrue()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#object") { + it("resolves cached object") { + let expectation = self.expectationWithDescription( + "Object Expectation") + + cache.add(key, object: object) + cache.object(key) { (receivedObject: User?) in + expect(receivedObject?.firstName).to(equal(object.firstName)) + expect(receivedObject?.lastName).to(equal(object.lastName)) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#remove") { + it("removes cached object") { + let expectation = self.expectationWithDescription( + "Remove Expectation") + + cache.add(key, object: object) + cache.remove(key) { + let fileExist = fileManager.fileExistsAtPath(cache.filePath(key)) + expect(fileExist).to(beFalse()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#clear") { + it("clears cache directory") { + let expectation = self.expectationWithDescription( + "Clear Expectation") + + cache.add(key, object: object) + cache.clear() { + let fileExist = fileManager.fileExistsAtPath(cache.path) + expect(fileExist).to(beFalse()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#fileName") { + it("returns a correct file name") { + expect(cache.fileName(key)).to(equal(key.base64())) + } + } + + describe("#filePath") { + it("returns a correct file path") { + let filePath = "\(cache.path)/\(cache.fileName(key))" + expect(cache.filePath(key)).to(equal(filePath)) + } + } + } + } +} diff --git a/Pod/Tests/Specs/Extensions/String+ExtensionsSpec.swift b/Pod/Tests/Specs/Extensions/String+ExtensionsSpec.swift new file mode 100644 index 00000000..61af98f6 --- /dev/null +++ b/Pod/Tests/Specs/Extensions/String+ExtensionsSpec.swift @@ -0,0 +1,24 @@ +import Quick +import Nimble + +class StringExtensionsSpec: QuickSpec { + + override func spec() { + describe("String+Extensions") { + + describe("#base64") { + it("returns the correct base64 string") { + let items = [ + "John Snow": "Sm9obiBTbm93", + "You know nothing": "WW91IGtub3cgbm90aGluZw==", + "Night's Watch": "TmlnaHQncyBXYXRjaA==" + ] + + for (key, value) in items { + expect(key.base64()).to(equal(value)) + } + } + } + } + } +} diff --git a/Pod/Tests/Specs/MemoryCacheSpec.swift b/Pod/Tests/Specs/MemoryCacheSpec.swift new file mode 100644 index 00000000..a358aeed --- /dev/null +++ b/Pod/Tests/Specs/MemoryCacheSpec.swift @@ -0,0 +1,100 @@ +import Quick +import Nimble + +class MemoryCacheSpec: QuickSpec { + + override func spec() { + describe("MemoryCache") { + let name = "DudeMemoryCache" + let key = "youknownothing" + let object = User(firstName: "John", lastName: "Snow") + var cache: MemoryCache! + + beforeEach { + cache = MemoryCache(name: name) + } + + afterEach { + cache.clear() + } + + describe("#path") { + it("returns the correct path") { + let path = "\(cache.prefix).\(name.capitalizedString)" + + expect(cache.path).to(equal(path)) + } + } + + describe("#maxSize") { + it("returns the default maximum size of a cache") { + expect(cache.maxSize).to(equal(0)) + } + } + + describe("#add") { + it("saves an object") { + let expectation = self.expectationWithDescription( + "Save Object Expectation") + + cache.add(key, object: object) + cache.object(key) { (receivedObject: User?) in + expect(receivedObject).toNot(beNil()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#object") { + it("resolves cached object") { + let expectation = self.expectationWithDescription( + "Object Expectation") + + cache.add(key, object: object) + cache.object(key) { (receivedObject: User?) in + expect(receivedObject?.firstName).to(equal(object.firstName)) + expect(receivedObject?.lastName).to(equal(object.lastName)) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#remove") { + it("removes cached object") { + let expectation = self.expectationWithDescription( + "Remove Expectation") + + cache.add(key, object: object) + cache.remove(key) + cache.object(key) { (receivedObject: User?) in + expect(receivedObject).to(beNil()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + + describe("#clear") { + it("clears cache directory") { + let expectation = self.expectationWithDescription( + "Clear Expectation") + + cache.add(key, object: object) + cache.clear() + + cache.object(key) { (receivedObject: User?) in + expect(receivedObject).to(beNil()) + expectation.fulfill() + } + + self.waitForExpectationsWithTimeout(2.0, handler:nil) + } + } + } + } +} diff --git a/Pod/Tests/Tests-Bridging-Header.h b/Pod/Tests/Tests-Bridging-Header.h deleted file mode 100644 index 1b2cb5d6..00000000 --- a/Pod/Tests/Tests-Bridging-Header.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - diff --git a/Pod/Tests/Tests.swift b/Pod/Tests/Tests.swift deleted file mode 100644 index 18300e14..00000000 --- a/Pod/Tests/Tests.swift +++ /dev/null @@ -1,10 +0,0 @@ -import UIKit -import XCTest - -class Tests: XCTestCase { - - func testFailing() { - let ofCourse = true - XCTAssertEqual(ofCourse, false) - } -} diff --git a/Source/Cachable.swift b/Source/Cachable.swift index 428f3f97..2b479004 100644 --- a/Source/Cachable.swift +++ b/Source/Cachable.swift @@ -3,6 +3,7 @@ import Foundation public protocol Cachable: AnyObject {} public extension Cachable { + func encode() -> NSData { var value = self return withUnsafePointer(&value) { p in @@ -10,9 +11,11 @@ public extension Cachable { } } - static func decode(data: NSData) -> T { - let pointer = UnsafeMutablePointer.alloc(sizeof(T.Type)) - data.getBytes(pointer, length: sizeof(T)) + static func decode(data: NSData) -> Self { + typealias CurrentSelf = Self + + let pointer = UnsafeMutablePointer.alloc(sizeof(CurrentSelf.Type)) + data.getBytes(pointer, length: sizeof(Self)) return pointer.move() } } diff --git a/Source/CacheAware.swift b/Source/CacheAware.swift index 5e14de69..14fdddab 100644 --- a/Source/CacheAware.swift +++ b/Source/CacheAware.swift @@ -1,12 +1,15 @@ +import Foundation + public protocol CacheAware { + var prefix: String { get } var path: String { get } var maxSize: UInt { get set } init(name: String) - func add(key: String, object: T) - func object(key: String) -> T? - func remove(key: String) - func clear() + func add(key: String, object: T, start: Bool, completion: (() -> Void)?) -> CacheTask? + func object(key: String, start: Bool, completion: (object: T?) -> Void) -> CacheTask? + func remove(key: String, start: Bool, completion: (() -> Void)?) -> CacheTask? + func clear(start: Bool, completion: (() -> Void)?) -> CacheTask? } diff --git a/Source/CacheTask.swift b/Source/CacheTask.swift new file mode 100644 index 00000000..fc917b5c --- /dev/null +++ b/Source/CacheTask.swift @@ -0,0 +1,21 @@ +import Foundation + +public class CacheTask { + + private var block: dispatch_block_t + + init(processing: () -> Void) { + block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS) { + processing() + } + } + + func start() -> Self { + dispatch_async(dispatch_get_main_queue(), block) + return self + } + + func cancel() { + dispatch_block_cancel(block) + } +} diff --git a/Source/DiskCache.swift b/Source/DiskCache.swift index 1322c8bb..2dfae23f 100644 --- a/Source/DiskCache.swift +++ b/Source/DiskCache.swift @@ -3,44 +3,116 @@ import Foundation public class DiskCache: CacheAware { public let prefix = "no.hyper.Cache.Disk" + public let ioQueueName = "no.hyper.Cache.Disk.IOQueue." public let path: String public var maxSize: UInt = 0 private var fileManager: NSFileManager! + private let ioQueue: dispatch_queue_t + + // MARK: - Initialization public required init(name: String) { + let cacheName = name.capitalizedString let paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true) - path = "\(paths.first!)/\(prefix)\(name)" + + path = "\(paths.first!)/\(prefix).\(cacheName)" + ioQueue = dispatch_queue_create("\(ioQueueName).\(cacheName)", DISPATCH_QUEUE_SERIAL) + + dispatch_sync(ioQueue) { + self.fileManager = NSFileManager() + } } // MARK: - CacheAware - public func add(key: String, object: T) { - if !fileManager.fileExistsAtPath(path) { - do { - try fileManager.createDirectoryAtPath(path, - withIntermediateDirectories: true, attributes: nil) - } catch _ {} + public func add(key: String, object: T, start: Bool = true, completion: (() -> Void)? = nil) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + + if !weakSelf.fileManager.fileExistsAtPath(weakSelf.path) { + do { + try weakSelf.fileManager.createDirectoryAtPath(weakSelf.path, + withIntermediateDirectories: true, attributes: nil) + } catch _ {} + } + + weakSelf.fileManager.createFileAtPath( + weakSelf.filePath(key), + contents: object.encode(), attributes: nil) + + dispatch_async(dispatch_get_main_queue()) { + completion?() + } } - fileManager.createFileAtPath(filePath(key), - contents: object.encode(), attributes: nil) + return start ? task.start() : task } - public func object(key: String) -> T? { - return nil + public func object(key: String, start: Bool = true, completion: (object: T?) -> Void) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + + dispatch_async(weakSelf.ioQueue) { + let filePath = weakSelf.filePath(key) + var cachedObject: T? + if let data = NSData(contentsOfFile: filePath) { + cachedObject = T.decode(data) + } + + dispatch_async(dispatch_get_main_queue()) { + completion(object: cachedObject) + } + } + } + + return start ? task.start() : task } - public func remove(key: String) { + public func remove(key: String, start: Bool = true, completion: (() -> Void)? = nil) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + + dispatch_async(weakSelf.ioQueue) { + do { + try weakSelf.fileManager.removeItemAtPath(weakSelf.filePath(key)) + } catch _ {} + + dispatch_async(dispatch_get_main_queue()) { + completion?() + } + } + } + + return start ? task.start() : task } - public func clear() { + public func clear(start: Bool = true, completion: (() -> Void)? = nil) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + + dispatch_async(weakSelf.ioQueue) { + do { + try weakSelf.fileManager.removeItemAtPath(weakSelf.path) + } catch _ {} + + dispatch_async(dispatch_get_main_queue()) { + completion?() + } + } + } + + return start ? task.start() : task } // MARK: - Helpers - private func filePath(key: String) -> String { - return "\(path)/key" + func fileName(key: String) -> String { + return key.base64() + } + + func filePath(key: String) -> String { + return "\(path)/\(fileName(key))" } } diff --git a/Source/Extensions/String+Base64.swift b/Source/Extensions/String+Extensions.swift similarity index 100% rename from Source/Extensions/String+Base64.swift rename to Source/Extensions/String+Extensions.swift diff --git a/Source/MemoryCache.swift b/Source/MemoryCache.swift index e440ed04..a5f32f1f 100644 --- a/Source/MemoryCache.swift +++ b/Source/MemoryCache.swift @@ -1,6 +1,7 @@ import Foundation public class MemoryCache: CacheAware { + public let prefix = "no.hyper.Cache.Memory" public var path: String { @@ -15,25 +16,50 @@ public class MemoryCache: CacheAware { public let cache = NSCache() + // MARK: - Initialization + public required init(name: String) { - cache.name = prefix + name + cache.name = "\(prefix).\(name.capitalizedString)" } // MARK: - CacheAware - public func add(key: String, object: T) { - cache.setObject(object, forKey: key) + public func add(key: String, object: T, start: Bool = true, completion: (() -> Void)? = nil) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + weakSelf.cache.setObject(object, forKey: key) + } + + return start ? task.start() : task } - public func object(key: String) -> T? { - return cache.objectForKey(key) as? T + public func object(key: String, start: Bool = true, completion: (object: T?) -> Void) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + let cachedObject = weakSelf.cache.objectForKey(key) as? T + completion(object: cachedObject) + } + + return start ? task.start() : task } - public func remove(key: String) { - cache.removeObjectForKey(key) + public func remove(key: String, start: Bool = true, completion: (() -> Void)? = nil) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + weakSelf.cache.removeObjectForKey(key) + completion?() + } + + return start ? task.start() : task } - public func clear() { - cache.removeAllObjects() + public func clear(start: Bool = true, completion: (() -> Void)? = nil) -> CacheTask? { + let task = CacheTask { [weak self] in + guard let weakSelf = self else { return } + weakSelf.cache.removeAllObjects() + completion?() + } + + return start ? task.start() : task } }