From 3ccd88ad7580bb3a7edf4017745e99bb0b608df1 Mon Sep 17 00:00:00 2001 From: Rizwan Date: Wed, 19 Sep 2018 22:15:10 +0530 Subject: [PATCH 01/73] Made the code compatible with Swift 4.2 by doing the following, Replaced the method UIImagePNGRepresentation(self) with self.pngData() Replaced the method UIImageJPEGRepresentation(self, 1.0) with self.jpegData(compressionQuality: 1.0) --- Cache.xcodeproj/project.pbxproj | 10 ++++++++-- Source/iOS/UIImage+Extensions.swift | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index f6e4bd1d..be257cbf 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -1027,6 +1027,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.2; }; @@ -1052,6 +1053,7 @@ PRODUCT_NAME = Cache; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.2; }; @@ -1143,6 +1145,7 @@ PRODUCT_NAME = Cache; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1165,6 +1168,7 @@ PRODUCT_NAME = Cache; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -1250,7 +1254,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1302,7 +1306,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1326,6 +1330,7 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1345,6 +1350,7 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/Source/iOS/UIImage+Extensions.swift b/Source/iOS/UIImage+Extensions.swift index abc8834c..dee0008b 100644 --- a/Source/iOS/UIImage+Extensions.swift +++ b/Source/iOS/UIImage+Extensions.swift @@ -23,7 +23,7 @@ extension UIImage { /// Convert to data func cache_toData() -> Data? { return hasAlpha - ? UIImagePNGRepresentation(self) - : UIImageJPEGRepresentation(self, 1.0) + ? self.pngData() + : self.jpegData(compressionQuality: 1.0) } } From d7d73bc5ac2c7adbd149d88e969a184ae08aca88 Mon Sep 17 00:00:00 2001 From: gaoxiang Date: Thu, 20 Sep 2018 09:03:39 +0800 Subject: [PATCH 02/73] update to support swift4+ --- Source/iOS/UIImage+Extensions.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/iOS/UIImage+Extensions.swift b/Source/iOS/UIImage+Extensions.swift index dee0008b..611990e1 100644 --- a/Source/iOS/UIImage+Extensions.swift +++ b/Source/iOS/UIImage+Extensions.swift @@ -22,8 +22,14 @@ extension UIImage { /// Convert to data func cache_toData() -> Data? { + #if swift(>=4.2) return hasAlpha - ? self.pngData() - : self.jpegData(compressionQuality: 1.0) + ? pngData() + : jpegData(compressionQuality: 1.0) + #else + return hasAlpha + ? UIImagePNGRepresentation(self) + : UIImageJPEGRepresentation(self, 1.0) + #endif } } From 3453f681c60799f779505a1af2b62f319b6c5a09 Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Sun, 23 Sep 2018 13:00:34 +0300 Subject: [PATCH 03/73] * setting Swift4.2 version in appropriate places * fixing tests for Swift 4.2 * Xcode 10 parallel testing * code sanitasion * remove comments from Package.swift --- .circleci/config.yml | 10 +++++----- .swift-version | 2 +- Cache.podspec | 4 ++-- Cache.xcodeproj/project.pbxproj | 6 ++++-- .../xcshareddata/xcschemes/Cache-iOS.xcscheme | 4 +++- .../xcshareddata/xcschemes/Cache-macOS.xcscheme | 4 +++- .../xcshareddata/xcschemes/Cache-tvOS.xcscheme | 4 +++- Package.swift | 10 ++-------- Source/Shared/Storage/DiskStorage.swift | 3 +-- Source/Shared/Storage/HybridStorage.swift | 4 ++-- Source/Shared/Storage/Storage.swift | 2 +- Tests/Shared/TestHelper.swift | 9 ++++++--- 12 files changed, 33 insertions(+), 29 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2e638711..23597874 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,19 +2,19 @@ version: 2 jobs: build-and-test: macos: - xcode: "9.3.0" + xcode: "10.0.0" shell: /bin/bash --login -o pipefail steps: - checkout - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-macOS" -sdk macosx clean - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-macOS" -sdk macosx -enableCodeCoverage YES test - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-iOS" -sdk iphonesimulator clean - - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-iOS" -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=11.3,name=iPhone X' -enableCodeCoverage YES test - - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=11.3' clean - - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=11.3' -enableCodeCoverage YES test + - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-iOS" -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=12.0,name=iPhone X' -enableCodeCoverage YES test + - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=12.0' clean + - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=12.0' -enableCodeCoverage YES test workflows: version: 2 build-and-test: jobs: - - build-and-test \ No newline at end of file + - build-and-test diff --git a/.swift-version b/.swift-version index 7d5c902e..bf77d549 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.1 +4.2 diff --git a/Cache.podspec b/Cache.podspec index 03a9cc37..7472be14 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "5.1.0" + s.version = "5.1.1" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.frameworks = 'Foundation' - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.1' } + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' } end diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index be257cbf..4074dd71 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -497,7 +497,9 @@ D5DC59FA1C205AC9003BD79B /* Tests */, D5DC59E11C20593E003BD79B /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; }; D5DC59E11C20593E003BD79B /* Products */ = { isa = PBXGroup; @@ -1109,7 +1111,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1122,7 +1124,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme index 637c74b1..d05b90d7 100644 --- a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme +++ b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme @@ -29,7 +29,9 @@ shouldUseLaunchSchemeArgsEnv = "YES"> + skipped = "NO" + parallelizable = "YES" + testExecutionOrdering = "random"> + skipped = "NO" + parallelizable = "YES" + testExecutionOrdering = "random"> + skipped = "NO" + parallelizable = "YES" + testExecutionOrdering = "random"> { var onRemove: ((String) -> Void)? private let transformer: Transformer - - // MARK: - Initialization + // MARK: - Initialization public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { let url: URL if let directory = config.directory { diff --git a/Source/Shared/Storage/HybridStorage.swift b/Source/Shared/Storage/HybridStorage.swift index 5e96fbce..52909680 100644 --- a/Source/Shared/Storage/HybridStorage.swift +++ b/Source/Shared/Storage/HybridStorage.swift @@ -109,7 +109,7 @@ extension HybridStorage: StorageObservationRegistry { self?.storageObservations.removeValue(forKey: id) } } - + public func removeAllStorageObservers() { storageObservations.removeAll() } @@ -155,7 +155,7 @@ extension HybridStorage: KeyObservationRegistry { } private func notifyObserver(about change: KeyChange, whereKey closure: ((String) -> Bool)) { - let observation = keyObservations.first { key, value in closure(key) }?.value + let observation = keyObservations.first { key, _ in closure(key) }?.value observation?(self, change) } diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index 63e0a698..71a4c2ec 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -94,7 +94,7 @@ extension Storage: KeyObservationRegistry { forKey key: String, closure: @escaping (O, Storage, KeyChange) -> Void ) -> ObservationToken { - return hybridStorage.addObserver(observer, forKey: key) { [weak self] observer, _ , change in + return hybridStorage.addObserver(observer, forKey: key) { [weak self] observer, _, change in guard let strongSelf = self else { return } closure(observer, strongSelf, change) } diff --git a/Tests/Shared/TestHelper.swift b/Tests/Shared/TestHelper.swift index ac2be5ac..8f01c0e9 100644 --- a/Tests/Shared/TestHelper.swift +++ b/Tests/Shared/TestHelper.swift @@ -13,9 +13,12 @@ struct TestHelper { } static func triggerApplicationEvents() { - #if !os(macOS) - NotificationCenter.default.post(name: .UIApplicationDidEnterBackground, object: nil) - NotificationCenter.default.post(name: .UIApplicationWillTerminate, object: nil) + #if (iOS) + NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: nil) + NotificationCenter.default.post(name: UIApplication.willTerminateNotification, object: nil) + #elseif os(tvOS) + NotificationCenter.default.post(name: Notification.Name.UIApplicationDidEnterBackground, object: nil) + NotificationCenter.default.post(name: Notification.Name.UIApplicationWillTerminate, object: nil) #else NotificationCenter.default.post(name: NSApplication.willTerminateNotification, object: nil) NotificationCenter.default.post(name: NSApplication.didResignActiveNotification, object: nil) From 8c42c575cf28b2ff0e780c9728721e9a8891c92e Mon Sep 17 00:00:00 2001 From: Khoa Pham Date: Mon, 24 Sep 2018 13:44:31 +0200 Subject: [PATCH 04/73] Use Swift 4.2 --- Cache.podspec | 2 +- Cache.xcodeproj/project.pbxproj | 42 +-------------------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/Cache.podspec b/Cache.podspec index 7472be14..b8c6c901 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "5.1.1" + s.version = "5.2.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 4074dd71..0f1b87c5 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -614,7 +614,6 @@ D5291D5C1C283B5300B702C9 /* Frameworks */, D5291D5D1C283B5300B702C9 /* Headers */, D5291D5E1C283B5300B702C9 /* Resources */, - BD58C3AE1CF2EA04003F7141 /* SwiftLint */, ); buildRules = ( ); @@ -651,7 +650,6 @@ D5DC59DC1C20593E003BD79B /* Frameworks */, D5DC59DD1C20593E003BD79B /* Headers */, D5DC59DE1C20593E003BD79B /* Resources */, - BD58C3AD1CF2E9FD003F7141 /* SwiftLint */, ); buildRules = ( ); @@ -765,34 +763,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - BD58C3AD1CF2E9FD003F7141 /* SwiftLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = SwiftLint; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; - }; - BD58C3AE1CF2EA04003F7141 /* SwiftLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = SwiftLint; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; - }; BDEDD3731DBCE616007416A6 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -804,7 +774,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -1029,7 +999,6 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.2; }; @@ -1055,7 +1024,6 @@ PRODUCT_NAME = Cache; SDKROOT = appletvos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.2; }; @@ -1077,7 +1045,6 @@ SDKROOT = appletvos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; TVOS_DEPLOYMENT_TARGET = 10.0; }; name = Debug; @@ -1096,7 +1063,6 @@ PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; - SWIFT_VERSION = 3.0; TVOS_DEPLOYMENT_TARGET = 10.0; }; name = Release; @@ -1111,7 +1077,6 @@ PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1124,7 +1089,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; }; name = Release; }; @@ -1147,7 +1111,6 @@ PRODUCT_NAME = Cache; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1170,7 +1133,6 @@ PRODUCT_NAME = Cache; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; }; name = Release; }; @@ -1332,7 +1294,6 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1352,7 +1313,6 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; }; name = Release; }; From fc8474cb6e4d97c0db91d72018ffacf0c591b77e Mon Sep 17 00:00:00 2001 From: Berger Date: Sat, 20 Oct 2018 13:31:24 -0500 Subject: [PATCH 05/73] Fix capitalization of `Async APIs` in `Table of Contents` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b8b3b49..023ab3e7 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ * [Storage](#storage) * [Configuration](#configuration) * [Sync APIs](#sync-apis) - * [Async APIS](#async-apis) + * [Async APIs](#async-apis) * [Expiry date](#expiry-date) * [Observations](#observations) * [Storage observations](#storage-observations) From ffc74c98d3009b3022e345b38996e2b37f8cbbf3 Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Sun, 11 Aug 2019 09:54:11 +0300 Subject: [PATCH 06/73] Project update * Swift 5 in podspec * Swift 5 for project file * fix warnings --- Cache.podspec | 3 ++- Cache.xcodeproj/project.pbxproj | 11 +++++++---- .../xcshareddata/xcschemes/Cache-iOS.xcscheme | 2 +- .../xcshareddata/xcschemes/Cache-macOS.xcscheme | 2 +- .../xcshareddata/xcschemes/Cache-tvOS.xcscheme | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Cache.podspec b/Cache.podspec index b8c6c901..460e489a 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -19,5 +19,6 @@ Pod::Spec.new do |s| s.frameworks = 'Foundation' - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' } + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5.0' } + s.swift_version = '5.0' end diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 0f1b87c5..db481463 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -667,7 +667,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1030; ORGANIZATIONNAME = "Hyper Interaktiv AS"; TargetAttributes = { BDEDD3551DBCE5B1007416A6 = { @@ -697,10 +697,11 @@ }; buildConfigurationList = D5DC59DA1C20593E003BD79B /* Build configuration list for PBXProject "Cache" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = D5DC59D61C20593E003BD79B; productRefGroup = D5DC59E11C20593E003BD79B /* Products */; @@ -1170,6 +1171,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -1218,7 +1220,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1229,6 +1231,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -1270,7 +1273,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; diff --git a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme index d05b90d7..46541e5e 100644 --- a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme +++ b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme @@ -1,6 +1,6 @@ Date: Sun, 11 Aug 2019 10:01:33 +0300 Subject: [PATCH 07/73] Update Xcode in Circle CI --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 23597874..64ff4a5d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: build-and-test: macos: - xcode: "10.0.0" + xcode: "10.3.0" shell: /bin/bash --login -o pipefail steps: - checkout From 00b6113d69f1e8729adf98a351d287fb3cf3ef66 Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Sat, 28 Sep 2019 13:25:51 +0300 Subject: [PATCH 08/73] Fixed build --- Package.swift | 2 +- Source/Mac/NSImage+Extensions.swift | 6 ++++++ Source/iOS/UIImage+Extensions.swift | 11 +++++------ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Package.swift b/Package.swift index 4646a13f..2b1721a1 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.2 +// swift-tools-version:5.1 import PackageDescription diff --git a/Source/Mac/NSImage+Extensions.swift b/Source/Mac/NSImage+Extensions.swift index 8cc4f61a..fc18f9ff 100644 --- a/Source/Mac/NSImage+Extensions.swift +++ b/Source/Mac/NSImage+Extensions.swift @@ -1,4 +1,8 @@ +#if canImport(AppKit) import AppKit +#endif + +#if os(OSX) /// Helper UIImage extension. extension NSImage { @@ -34,3 +38,5 @@ extension NSImage { .representation(using: imageFileType, properties: [:]) } } + +#endif diff --git a/Source/iOS/UIImage+Extensions.swift b/Source/iOS/UIImage+Extensions.swift index 611990e1..afc2da81 100644 --- a/Source/iOS/UIImage+Extensions.swift +++ b/Source/iOS/UIImage+Extensions.swift @@ -1,4 +1,8 @@ +#if canImport(UIKit) import UIKit +#endif + +#if os(iOS) || os(watchOS) || os(tvOS) /// Helper UIImage extension. extension UIImage { @@ -22,14 +26,9 @@ extension UIImage { /// Convert to data func cache_toData() -> Data? { - #if swift(>=4.2) return hasAlpha ? pngData() : jpegData(compressionQuality: 1.0) - #else - return hasAlpha - ? UIImagePNGRepresentation(self) - : UIImageJPEGRepresentation(self, 1.0) - #endif } } +#endif From 620d4730448981be5a7b0125880341ae038153ff Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Sat, 28 Sep 2019 13:33:29 +0300 Subject: [PATCH 09/73] Fix build --- Cache.xcodeproj/project.pbxproj | 2 +- Package.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index db481463..1ad19d9b 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -189,7 +189,7 @@ D270148B20D113EA003B45C7 /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = ""; }; D270148F20D1251E003B45C7 /* TypeWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypeWrapper.swift; sourceTree = ""; }; D270149320D125AC003B45C7 /* MemoryCapsule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryCapsule.swift; sourceTree = ""; }; - D27014A420D129EB003B45C7 /* TransformerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransformerFactory.swift; sourceTree = ""; }; + D27014A420D129EB003B45C7 /* TransformerFactory.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = TransformerFactory.swift; sourceTree = ""; tabWidth = 4; }; D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectConverterTests.swift; sourceTree = ""; }; D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+Extensions.swift"; sourceTree = ""; }; D292DAFC1F6A970B0060F614 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; diff --git a/Package.swift b/Package.swift index 2b1721a1..a11a05c3 100644 --- a/Package.swift +++ b/Package.swift @@ -13,8 +13,8 @@ let package = Package( targets: [ .target( name: "Cache", - path: "Source/Shared", - exclude: ["Library/ImageWrapper.swift"]), // relative to the target path + path: "Source", + exclude: ["Library/ImageWrapper.swift"]), .testTarget( name: "CacheTests", dependencies: ["Cache"], From 9e4ec388aada963cb6c3ce68fcac6abdcadd4320 Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Sat, 28 Sep 2019 14:06:39 +0300 Subject: [PATCH 10/73] Fix platform specifics --- Package.swift | 3 ++- Source/Mac/NSImage+Extensions.swift | 3 --- Source/iOS/UIImage+Extensions.swift | 3 --- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Package.swift b/Package.swift index a11a05c3..c6fcee49 100644 --- a/Package.swift +++ b/Package.swift @@ -19,5 +19,6 @@ let package = Package( name: "CacheTests", dependencies: ["Cache"], path: "Tests"), - ] + ], + swiftLanguageVersions: [.v5] ) diff --git a/Source/Mac/NSImage+Extensions.swift b/Source/Mac/NSImage+Extensions.swift index fc18f9ff..8ebbc9ae 100644 --- a/Source/Mac/NSImage+Extensions.swift +++ b/Source/Mac/NSImage+Extensions.swift @@ -1,8 +1,5 @@ #if canImport(AppKit) import AppKit -#endif - -#if os(OSX) /// Helper UIImage extension. extension NSImage { diff --git a/Source/iOS/UIImage+Extensions.swift b/Source/iOS/UIImage+Extensions.swift index afc2da81..7ef012af 100644 --- a/Source/iOS/UIImage+Extensions.swift +++ b/Source/iOS/UIImage+Extensions.swift @@ -1,8 +1,5 @@ #if canImport(UIKit) import UIKit -#endif - -#if os(iOS) || os(watchOS) || os(tvOS) /// Helper UIImage extension. extension UIImage { From fa7f1aadd88428d05ff3bfcf7096a10a3f888a18 Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Tue, 1 Oct 2019 22:02:57 +0300 Subject: [PATCH 11/73] Bumped Xcode for CircleCI --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64ff4a5d..7b98b5d6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,16 +2,16 @@ version: 2 jobs: build-and-test: macos: - xcode: "10.3.0" + xcode: "11.0.0" shell: /bin/bash --login -o pipefail steps: - checkout - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-macOS" -sdk macosx clean - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-macOS" -sdk macosx -enableCodeCoverage YES test - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-iOS" -sdk iphonesimulator clean - - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-iOS" -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=12.0,name=iPhone X' -enableCodeCoverage YES test - - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=12.0' clean - - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=12.0' -enableCodeCoverage YES test + - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-iOS" -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=13.1,name=iPhone 11 Pro' -enableCodeCoverage YES test + - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=13.0' clean + - run: xcodebuild -project Cache.xcodeproj -scheme "Cache-tvOS" -destination 'platform=tvOS Simulator,name=Apple TV,OS=13.0' -enableCodeCoverage YES test workflows: version: 2 From 3f253eae331f45468721cbf2b9d5564309e56ac1 Mon Sep 17 00:00:00 2001 From: Elvis Date: Thu, 4 Jun 2020 21:10:51 -0500 Subject: [PATCH 12/73] Update tests --- Tests/Shared/TestHelper.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/Shared/TestHelper.swift b/Tests/Shared/TestHelper.swift index 8f01c0e9..4db29590 100644 --- a/Tests/Shared/TestHelper.swift +++ b/Tests/Shared/TestHelper.swift @@ -9,7 +9,7 @@ import AppKit struct TestHelper { static func data(_ length : Int) -> Data { let buffer = [UInt8](repeating: 0, count: length) - return Data(bytes: buffer) + return Data(buffer) } static func triggerApplicationEvents() { @@ -17,11 +17,11 @@ struct TestHelper { NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.post(name: UIApplication.willTerminateNotification, object: nil) #elseif os(tvOS) - NotificationCenter.default.post(name: Notification.Name.UIApplicationDidEnterBackground, object: nil) - NotificationCenter.default.post(name: Notification.Name.UIApplicationWillTerminate, object: nil) + NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: nil) + NotificationCenter.default.post(name: UIApplication.willTerminateNotification, object: nil) #else - NotificationCenter.default.post(name: NSApplication.willTerminateNotification, object: nil) - NotificationCenter.default.post(name: NSApplication.didResignActiveNotification, object: nil) + NotificationCenter.default.post(name: NSApplication.willTerminateNotification, object: nil) + NotificationCenter.default.post(name: NSApplication.didResignActiveNotification, object: nil) #endif } } From 427ee1cdb396aa5e2916fb82c7c7aa6babc158ff Mon Sep 17 00:00:00 2001 From: Elvis <3lvis@users.noreply.github.com> Date: Thu, 4 Jun 2020 21:17:13 -0500 Subject: [PATCH 13/73] Update Cache.podspec --- Cache.podspec | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Cache.podspec b/Cache.podspec index 460e489a..fb22ae9a 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "5.2.0" + s.version = "5.3.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } @@ -16,9 +16,7 @@ Pod::Spec.new do |s| s.ios.source_files = 'Source/{iOS,Shared}/**/*' s.osx.source_files = 'Source/{Mac,Shared}/**/*' s.tvos.source_files = 'Source/{iOS,Shared}/**/*' - + s.frameworks = 'Foundation' - - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5.0' } s.swift_version = '5.0' end From 042b2cd22d3c8c30fdcead0c613de94a1d648123 Mon Sep 17 00:00:00 2001 From: Elvis <3lvis@users.noreply.github.com> Date: Thu, 4 Jun 2020 21:17:28 -0500 Subject: [PATCH 14/73] Delete .swift-version --- .swift-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .swift-version diff --git a/.swift-version b/.swift-version deleted file mode 100644 index bf77d549..00000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -4.2 From aace3c727c08daf8bb3f8b431be9cf893bc9b874 Mon Sep 17 00:00:00 2001 From: Elvis Date: Tue, 25 Aug 2020 14:46:02 -0500 Subject: [PATCH 15/73] Updated MD5 --- Source/Shared/Library/MD5.swift | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Source/Shared/Library/MD5.swift b/Source/Shared/Library/MD5.swift index 2c2c857d..eb6e627c 100644 --- a/Source/Shared/Library/MD5.swift +++ b/Source/Shared/Library/MD5.swift @@ -1,7 +1,3 @@ -// swiftlint:disable comma function_parameter_count variable_name syntactic_sugar function_body_length vertical_whitespace - -// https://github.com/onmyway133/SwiftHash/blob/master/Sources/MD5.swift - /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. @@ -103,13 +99,10 @@ func rstr_md5(_ input: [CUnsignedChar]) -> [CUnsignedChar] { } /* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. + * Add integers, wrapping at 2^32. */ func safe_add(_ x: Int32, _ y: Int32) -> Int32 { - let lsw = (x & 0xFFFF) + (y & 0xFFFF) - let msw = (x >> 16) + (y >> 16) + (lsw >> 16) - return (msw << 16) | (lsw & 0xFFFF) + return x &+ y } /* From 6272726c2c696651977bef5bb0b0a275e66de77e Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 12:26:28 +0200 Subject: [PATCH 16/73] Remove compiler errors in tests for the scenario of running tests via SPM --- Tests/Mac/Helpers/NSImage+ExtensionsTests.swift | 2 ++ Tests/Mac/Helpers/TestHelper+OSX.swift | 2 ++ Tests/Shared/TestHelper.swift | 2 +- Tests/iOS/Helpers/TestHelper+iOS.swift | 2 ++ Tests/iOS/Helpers/UIImage+ExtensionsTests.swift | 2 ++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Tests/Mac/Helpers/NSImage+ExtensionsTests.swift b/Tests/Mac/Helpers/NSImage+ExtensionsTests.swift index b0cbc017..06569892 100644 --- a/Tests/Mac/Helpers/NSImage+ExtensionsTests.swift +++ b/Tests/Mac/Helpers/NSImage+ExtensionsTests.swift @@ -1,3 +1,4 @@ +#if os(macOS) import Cocoa @testable import Cache @@ -14,3 +15,4 @@ extension NSImage { .representation(using: imageFileType, properties: [:])! } } +#endif diff --git a/Tests/Mac/Helpers/TestHelper+OSX.swift b/Tests/Mac/Helpers/TestHelper+OSX.swift index 35e35f68..a7def2fa 100644 --- a/Tests/Mac/Helpers/TestHelper+OSX.swift +++ b/Tests/Mac/Helpers/TestHelper+OSX.swift @@ -1,3 +1,4 @@ +#if os(macOS) import Cocoa extension TestHelper { @@ -9,3 +10,4 @@ extension TestHelper { return image } } +#endif diff --git a/Tests/Shared/TestHelper.swift b/Tests/Shared/TestHelper.swift index 4db29590..6e8e5963 100644 --- a/Tests/Shared/TestHelper.swift +++ b/Tests/Shared/TestHelper.swift @@ -19,7 +19,7 @@ struct TestHelper { #elseif os(tvOS) NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.post(name: UIApplication.willTerminateNotification, object: nil) - #else + #elseif os(macOS) NotificationCenter.default.post(name: NSApplication.willTerminateNotification, object: nil) NotificationCenter.default.post(name: NSApplication.didResignActiveNotification, object: nil) #endif diff --git a/Tests/iOS/Helpers/TestHelper+iOS.swift b/Tests/iOS/Helpers/TestHelper+iOS.swift index a1a41671..ab840d04 100644 --- a/Tests/iOS/Helpers/TestHelper+iOS.swift +++ b/Tests/iOS/Helpers/TestHelper+iOS.swift @@ -1,3 +1,4 @@ +#if os(iOS) || os(tvOS) import UIKit extension TestHelper { @@ -14,3 +15,4 @@ extension TestHelper { return image! } } +#endif diff --git a/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift b/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift index 2b9c92b4..307a0578 100644 --- a/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift +++ b/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift @@ -1,3 +1,4 @@ +#if os(iOS) || os(tvOS) import UIKit extension UIImage { @@ -24,3 +25,4 @@ extension UIImage { return drawnImage!.cgImage!.dataProvider!.data! as Data } } +#endif From 8a645275044e93a13c8657e54a5b74a3dfa590d7 Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 12:27:02 +0200 Subject: [PATCH 17/73] Add constant across executions variant of hasher --- .../Hasher+constantAccrossExecutions.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift diff --git a/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift b/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift new file mode 100644 index 00000000..1406a54f --- /dev/null +++ b/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift @@ -0,0 +1,26 @@ + +import Foundation + +extension Hasher { + // Stolen from https://github.com/apple/swift/blob/master/stdlib/public/core/SipHash.swift + // in order to replicate the exact format in bytes + private struct _State { + private var v0: UInt64 = 0x736f6d6570736575 + private var v1: UInt64 = 0x646f72616e646f6d + private var v2: UInt64 = 0x6c7967656e657261 + private var v3: UInt64 = 0x7465646279746573 + private var v4: UInt64 = 0 + private var v5: UInt64 = 0 + private var v6: UInt64 = 0 + private var v7: UInt64 = 0 + } + + static func constantAccrossExecutions() -> Hasher { + let offset = MemoryLayout.size - MemoryLayout<_State>.size + var hasher = Hasher() + withUnsafeMutableBytes(of: &hasher) { pointer in + pointer.baseAddress!.storeBytes(of: _State(), toByteOffset: offset, as: _State.self) + } + return hasher + } +} From 98f7a3bb282fecd03d2012e43eada9361da83e7d Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 12:27:27 +0200 Subject: [PATCH 18/73] Add test for hasher constant accross executions --- .../Hasher+constantAccrossExecutions+Tests.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Tests/iOS/Tests/Extensions/Hasher+constantAccrossExecutions+Tests.swift diff --git a/Tests/iOS/Tests/Extensions/Hasher+constantAccrossExecutions+Tests.swift b/Tests/iOS/Tests/Extensions/Hasher+constantAccrossExecutions+Tests.swift new file mode 100644 index 00000000..e75397db --- /dev/null +++ b/Tests/iOS/Tests/Extensions/Hasher+constantAccrossExecutions+Tests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import Cache + +final class HasherConstantAccrossExecutionsTests: XCTestCase { + func testHashValueRemainsTheSameAsLastTime() { + // Warning: this test may start failing after a Swift Update + let value = "some string with some values" + var hasher = Hasher.constantAccrossExecutions() + value.hash(into: &hasher) + XCTAssertEqual(hasher.finalize(), -4706942985426845298) + } +} From 517cbf554a1d51461748212e4628a0e4c0fe9422 Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 12:32:29 +0200 Subject: [PATCH 19/73] Generalize cache storage to allow using any hashable key parameter --- Source/Shared/Storage/AsyncStorage.swift | 26 +++++----- Source/Shared/Storage/DiskStorage.swift | 47 +++++++++++-------- Source/Shared/Storage/HybridStorage.swift | 40 ++++++++-------- .../Storage/KeyObservationRegistry.swift | 6 +-- Source/Shared/Storage/MemoryStorage.swift | 44 +++++++++++------ Source/Shared/Storage/Storage+Transform.swift | 6 +-- Source/Shared/Storage/Storage.swift | 34 +++++++------- Source/Shared/Storage/StorageAware.swift | 23 ++++----- .../Storage/StorageObservationRegistry.swift | 10 ++-- Source/Shared/Storage/SyncStorage.swift | 18 +++---- 10 files changed, 139 insertions(+), 115 deletions(-) diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index dcd5e6b4..9a119946 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -3,18 +3,18 @@ import Dispatch /// Manipulate storage in a "all async" manner. /// The completion closure will be called when operation completes. -public class AsyncStorage { - public let innerStorage: HybridStorage +public class AsyncStorage { + public let innerStorage: HybridStorage public let serialQueue: DispatchQueue - public init(storage: HybridStorage, serialQueue: DispatchQueue) { + public init(storage: HybridStorage, serialQueue: DispatchQueue) { self.innerStorage = storage self.serialQueue = serialQueue } } extension AsyncStorage { - public func entry(forKey key: String, completion: @escaping (Result>) -> Void) { + public func entry(forKey key: Key, completion: @escaping (Result>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { completion(Result.error(StorageError.deallocated)) @@ -30,7 +30,7 @@ extension AsyncStorage { } } - public func removeObject(forKey key: String, completion: @escaping (Result<()>) -> Void) { + public func removeObject(forKey key: Key, completion: @escaping (Result<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { completion(Result.error(StorageError.deallocated)) @@ -47,8 +47,8 @@ extension AsyncStorage { } public func setObject( - _ object: T, - forKey key: String, + _ object: Value, + forKey key: Key, expiry: Expiry? = nil, completion: @escaping (Result<()>) -> Void) { serialQueue.async { [weak self] in @@ -98,8 +98,8 @@ extension AsyncStorage { } } - public func object(forKey key: String, completion: @escaping (Result) -> Void) { - entry(forKey: key, completion: { (result: Result>) in + public func object(forKey key: Key, completion: @escaping (Result) -> Void) { + entry(forKey: key, completion: { (result: Result>) in completion(result.map({ entry in return entry.object })) @@ -107,9 +107,9 @@ extension AsyncStorage { } public func existsObject( - forKey key: String, + forKey key: Key, completion: @escaping (Result) -> Void) { - object(forKey: key, completion: { (result: Result) in + object(forKey: key, completion: { (result: Result) in completion(result.map({ _ in return true })) @@ -118,8 +118,8 @@ extension AsyncStorage { } public extension AsyncStorage { - func transform(transformer: Transformer) -> AsyncStorage { - let storage = AsyncStorage( + func transform(transformer: Transformer) -> AsyncStorage { + let storage = AsyncStorage( storage: innerStorage.transform(transformer: transformer), serialQueue: serialQueue ) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index d02be787..76f4cd02 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -1,7 +1,7 @@ import Foundation /// Save objects to file on disk -final public class DiskStorage { +final public class DiskStorage { enum Error: Swift.Error { case fileEnumeratorFailed } @@ -15,10 +15,11 @@ final public class DiskStorage { /// The closure to be called when single file has been removed var onRemove: ((String) -> Void)? - private let transformer: Transformer + private let transformer: Transformer + private let hasher = Hasher.constantAccrossExecutions() // MARK: - Initialization - public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { + public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { let url: URL if let directory = config.directory { url = directory @@ -48,7 +49,7 @@ final public class DiskStorage { #endif } - public required init(config: DiskConfig, fileManager: FileManager = FileManager.default, path: String, transformer: Transformer) { + public required init(config: DiskConfig, fileManager: FileManager = FileManager.default, path: String, transformer: Transformer) { self.config = config self.fileManager = fileManager self.path = path @@ -57,7 +58,7 @@ final public class DiskStorage { } extension DiskStorage: StorageAware { - public func entry(forKey key: String) throws -> Entry { + public func entry(forKey key: Key) throws -> Entry { let filePath = makeFilePath(for: key) let data = try Data(contentsOf: URL(fileURLWithPath: filePath)) let attributes = try fileManager.attributesOfItem(atPath: filePath) @@ -74,7 +75,7 @@ extension DiskStorage: StorageAware { ) } - public func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws { + public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) throws { let expiry = expiry ?? config.expiry let data = try transformer.toData(object) let filePath = makeFilePath(for: key) @@ -82,7 +83,7 @@ extension DiskStorage: StorageAware { try fileManager.setAttributes([.modificationDate: expiry.date], ofItemAtPath: filePath) } - public func removeObject(forKey key: String) throws { + public func removeObject(forKey key: Key) throws { let filePath = makeFilePath(for: key) try fileManager.removeItem(atPath: filePath) onRemove?(filePath) @@ -160,16 +161,22 @@ extension DiskStorage { - Parameter key: Unique key to identify the object in the cache - Returns: A md5 string */ - func makeFileName(for key: String) -> String { - let fileExtension = URL(fileURLWithPath: key).pathExtension - let fileName = MD5(key) - - switch fileExtension.isEmpty { - case true: - return fileName - case false: - return "\(fileName).\(fileExtension)" + func makeFileName(for key: Key) -> String { + if let key = key as? String { + let fileExtension = URL(fileURLWithPath: key).pathExtension + let fileName = MD5(key) + + switch fileExtension.isEmpty { + case true: + return fileName + case false: + return "\(fileName).\(fileExtension)" + } } + + var hasher = self.hasher + key.hash(into: &hasher) + return String(hasher.finalize()) } /** @@ -177,7 +184,7 @@ extension DiskStorage { - Parameter key: Unique key to identify the object in the cache - Returns: A string path based on key */ - func makeFilePath(for key: String) -> String { + func makeFilePath(for key: Key) -> String { return "\(path)/\(makeFileName(for: key))" } @@ -244,7 +251,7 @@ extension DiskStorage { Removes the object from the cache if it's expired. - Parameter key: Unique key to identify the object in the cache */ - func removeObjectIfExpired(forKey key: String) throws { + func removeObjectIfExpired(forKey key: Key) throws { let filePath = makeFilePath(for: key) let attributes = try fileManager.attributesOfItem(atPath: filePath) if let expiryDate = attributes[.modificationDate] as? Date, expiryDate.inThePast { @@ -255,8 +262,8 @@ extension DiskStorage { } public extension DiskStorage { - func transform(transformer: Transformer) -> DiskStorage { - let storage = DiskStorage( + func transform(transformer: Transformer) -> DiskStorage { + let storage = DiskStorage( config: config, fileManager: fileManager, path: path, diff --git a/Source/Shared/Storage/HybridStorage.swift b/Source/Shared/Storage/HybridStorage.swift index 52909680..6a529ccf 100644 --- a/Source/Shared/Storage/HybridStorage.swift +++ b/Source/Shared/Storage/HybridStorage.swift @@ -1,14 +1,14 @@ import Foundation /// Use both memory and disk storage. Try on memory first. -public final class HybridStorage { - public let memoryStorage: MemoryStorage - public let diskStorage: DiskStorage +public final class HybridStorage { + public let memoryStorage: MemoryStorage + public let diskStorage: DiskStorage - private(set) var storageObservations = [UUID: (HybridStorage, StorageChange) -> Void]() - private(set) var keyObservations = [String: (HybridStorage, KeyChange) -> Void]() + private(set) var storageObservations = [UUID: (HybridStorage, StorageChange) -> Void]() + private(set) var keyObservations = [Key: (HybridStorage, KeyChange) -> Void]() - public init(memoryStorage: MemoryStorage, diskStorage: DiskStorage) { + public init(memoryStorage: MemoryStorage, diskStorage: DiskStorage) { self.memoryStorage = memoryStorage self.diskStorage = diskStorage @@ -26,7 +26,7 @@ public final class HybridStorage { } extension HybridStorage: StorageAware { - public func entry(forKey key: String) throws -> Entry { + public func entry(forKey key: Key) throws -> Entry { do { return try memoryStorage.entry(forKey: key) } catch { @@ -37,15 +37,15 @@ extension HybridStorage: StorageAware { } } - public func removeObject(forKey key: String) throws { + public func removeObject(forKey key: Key) throws { memoryStorage.removeObject(forKey: key) try diskStorage.removeObject(forKey: key) notifyStorageObservers(about: .remove(key: key)) } - public func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws { - var keyChange: KeyChange? + public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) throws { + var keyChange: KeyChange? if keyObservations[key] != nil { keyChange = .edit(before: try? self.object(forKey: key), after: object) @@ -78,8 +78,8 @@ extension HybridStorage: StorageAware { } public extension HybridStorage { - func transform(transformer: Transformer) -> HybridStorage { - let storage = HybridStorage( + func transform(transformer: Transformer) -> HybridStorage { + let storage = HybridStorage( memoryStorage: memoryStorage.transform(), diskStorage: diskStorage.transform(transformer: transformer) ) @@ -92,7 +92,7 @@ extension HybridStorage: StorageObservationRegistry { @discardableResult public func addStorageObserver( _ observer: O, - closure: @escaping (O, HybridStorage, StorageChange) -> Void + closure: @escaping (O, HybridStorage, StorageChange) -> Void ) -> ObservationToken { let id = UUID() @@ -114,7 +114,7 @@ extension HybridStorage: StorageObservationRegistry { storageObservations.removeAll() } - private func notifyStorageObservers(about change: StorageChange) { + private func notifyStorageObservers(about change: StorageChange) { storageObservations.values.forEach { closure in closure(self, change) } @@ -125,8 +125,8 @@ extension HybridStorage: KeyObservationRegistry { @discardableResult public func addObserver( _ observer: O, - forKey key: String, - closure: @escaping (O, HybridStorage, KeyChange) -> Void + forKey key: Key, + closure: @escaping (O, HybridStorage, KeyChange) -> Void ) -> ObservationToken { keyObservations[key] = { [weak self, weak observer] storage, change in guard let observer = observer else { @@ -142,7 +142,7 @@ extension HybridStorage: KeyObservationRegistry { } } - public func removeObserver(forKey key: String) { + public func removeObserver(forKey key: Key) { keyObservations.removeValue(forKey: key) } @@ -150,16 +150,16 @@ extension HybridStorage: KeyObservationRegistry { keyObservations.removeAll() } - private func notifyObserver(forKey key: String, about change: KeyChange) { + private func notifyObserver(forKey key: Key, about change: KeyChange) { keyObservations[key]?(self, change) } - private func notifyObserver(about change: KeyChange, whereKey closure: ((String) -> Bool)) { + private func notifyObserver(about change: KeyChange, whereKey closure: ((Key) -> Bool)) { let observation = keyObservations.first { key, _ in closure(key) }?.value observation?(self, change) } - private func notifyKeyObservers(about change: KeyChange) { + private func notifyKeyObservers(about change: KeyChange) { keyObservations.values.forEach { closure in closure(self, change) } diff --git a/Source/Shared/Storage/KeyObservationRegistry.swift b/Source/Shared/Storage/KeyObservationRegistry.swift index 440bbef9..f231be12 100644 --- a/Source/Shared/Storage/KeyObservationRegistry.swift +++ b/Source/Shared/Storage/KeyObservationRegistry.swift @@ -15,15 +15,15 @@ public protocol KeyObservationRegistry { @discardableResult func addObserver( _ observer: O, - forKey key: String, - closure: @escaping (O, S, KeyChange) -> Void + forKey key: S.Key, + closure: @escaping (O, S, KeyChange) -> Void ) -> ObservationToken /** Removes observer by the given key. - Parameter key: Unique key to identify the object in the cache */ - func removeObserver(forKey key: String) + func removeObserver(forKey key: S.Key) /// Removes all registered key observers func removeAllKeyObservers() diff --git a/Source/Shared/Storage/MemoryStorage.swift b/Source/Shared/Storage/MemoryStorage.swift index c98655ee..6ab4b6df 100644 --- a/Source/Shared/Storage/MemoryStorage.swift +++ b/Source/Shared/Storage/MemoryStorage.swift @@ -1,9 +1,25 @@ import Foundation -public class MemoryStorage: StorageAware { - fileprivate let cache = NSCache() +public class MemoryStorage: StorageAware { + final class WrappedKey: NSObject { + let key: Key + + init(_ key: Key) { self.key = key } + + override var hash: Int { return key.hashValue } + + override func isEqual(_ object: Any?) -> Bool { + guard let value = object as? WrappedKey else { + return false + } + + return value.key == key + } + } + + fileprivate let cache = NSCache() // Memory cache keys - fileprivate var keys = Set() + fileprivate var keys = Set() /// Configuration fileprivate let config: MemoryConfig @@ -15,9 +31,9 @@ public class MemoryStorage: StorageAware { } extension MemoryStorage { - public func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) { + public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) { let capsule = MemoryCapsule(value: object, expiry: .date(expiry?.date ?? config.expiry.date)) - cache.setObject(capsule, forKey: NSString(string: key)) + cache.setObject(capsule, forKey: WrappedKey(key)) keys.insert(key) } @@ -33,23 +49,23 @@ extension MemoryStorage { } } - public func removeObjectIfExpired(forKey key: String) { - if let capsule = cache.object(forKey: NSString(string: key)), capsule.expiry.isExpired { + public func removeObjectIfExpired(forKey key: Key) { + if let capsule = cache.object(forKey: WrappedKey(key)), capsule.expiry.isExpired { removeObject(forKey: key) } } - public func removeObject(forKey key: String) { - cache.removeObject(forKey: NSString(string: key)) + public func removeObject(forKey key: Key) { + cache.removeObject(forKey: WrappedKey(key)) keys.remove(key) } - public func entry(forKey key: String) throws -> Entry { - guard let capsule = cache.object(forKey: NSString(string: key)) else { + public func entry(forKey key: Key) throws -> Entry { + guard let capsule = cache.object(forKey: WrappedKey(key)) else { throw StorageError.notFound } - guard let object = capsule.object as? T else { + guard let object = capsule.object as? Value else { throw StorageError.typeNotMatch } @@ -58,8 +74,8 @@ extension MemoryStorage { } public extension MemoryStorage { - func transform() -> MemoryStorage { - let storage = MemoryStorage(config: config) + func transform() -> MemoryStorage { + let storage = MemoryStorage(config: config) return storage } } diff --git a/Source/Shared/Storage/Storage+Transform.swift b/Source/Shared/Storage/Storage+Transform.swift index d628fd8c..a8db5ddc 100644 --- a/Source/Shared/Storage/Storage+Transform.swift +++ b/Source/Shared/Storage/Storage+Transform.swift @@ -1,17 +1,17 @@ import Foundation public extension Storage { - func transformData() -> Storage { + func transformData() -> Storage { let storage = transform(transformer: TransformerFactory.forData()) return storage } - func transformImage() -> Storage { + func transformImage() -> Storage { let storage = transform(transformer: TransformerFactory.forImage()) return storage } - func transformCodable(ofType: U.Type) -> Storage { + func transformCodable(ofType: U.Type) -> Storage { let storage = transform(transformer: TransformerFactory.forCodable(ofType: U.self)) return storage } diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index 71a4c2ec..f3749cc8 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -3,11 +3,11 @@ import Dispatch /// Manage storage. Use memory storage if specified. /// Synchronous by default. Use `async` for asynchronous operations. -public final class Storage { +public final class Storage { /// Used for sync operations - private let syncStorage: SyncStorage - private let asyncStorage: AsyncStorage - private let hybridStorage: HybridStorage + private let syncStorage: SyncStorage + private let asyncStorage: AsyncStorage + private let hybridStorage: HybridStorage /// Initialize storage with configuration options. /// @@ -15,9 +15,9 @@ public final class Storage { /// - diskConfig: Configuration for disk storage /// - memoryConfig: Optional. Pass config if you want memory cache /// - Throws: Throw StorageError if any. - public convenience init(diskConfig: DiskConfig, memoryConfig: MemoryConfig, transformer: Transformer) throws { - let disk = try DiskStorage(config: diskConfig, transformer: transformer) - let memory = MemoryStorage(config: memoryConfig) + public convenience init(diskConfig: DiskConfig, memoryConfig: MemoryConfig, transformer: Transformer) throws { + let disk = try DiskStorage(config: diskConfig, transformer: transformer) + let memory = MemoryStorage(config: memoryConfig) let hybridStorage = HybridStorage(memoryStorage: memory, diskStorage: disk) self.init(hybridStorage: hybridStorage) } @@ -26,7 +26,7 @@ public final class Storage { /// /// - Parameter syncStorage: Synchronous storage /// - Paraeter: asyncStorage: Asynchronous storage - public init(hybridStorage: HybridStorage) { + public init(hybridStorage: HybridStorage) { self.hybridStorage = hybridStorage self.syncStorage = SyncStorage( storage: hybridStorage, @@ -43,15 +43,15 @@ public final class Storage { } extension Storage: StorageAware { - public func entry(forKey key: String) throws -> Entry { + public func entry(forKey key: Key) throws -> Entry { return try self.syncStorage.entry(forKey: key) } - public func removeObject(forKey key: String) throws { + public func removeObject(forKey key: Key) throws { try self.syncStorage.removeObject(forKey: key) } - public func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws { + public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) throws { try self.syncStorage.setObject(object, forKey: key, expiry: expiry) } @@ -65,8 +65,8 @@ extension Storage: StorageAware { } public extension Storage { - func transform(transformer: Transformer) -> Storage { - return Storage(hybridStorage: hybridStorage.transform(transformer: transformer)) + func transform(transformer: Transformer) -> Storage { + return Storage(hybridStorage: hybridStorage.transform(transformer: transformer)) } } @@ -74,7 +74,7 @@ extension Storage: StorageObservationRegistry { @discardableResult public func addStorageObserver( _ observer: O, - closure: @escaping (O, Storage, StorageChange) -> Void + closure: @escaping (O, Storage, StorageChange) -> Void ) -> ObservationToken { return hybridStorage.addStorageObserver(observer) { [weak self] observer, _, change in guard let strongSelf = self else { return } @@ -91,8 +91,8 @@ extension Storage: KeyObservationRegistry { @discardableResult public func addObserver( _ observer: O, - forKey key: String, - closure: @escaping (O, Storage, KeyChange) -> Void + forKey key: Key, + closure: @escaping (O, Storage, KeyChange) -> Void ) -> ObservationToken { return hybridStorage.addObserver(observer, forKey: key) { [weak self] observer, _, change in guard let strongSelf = self else { return } @@ -100,7 +100,7 @@ extension Storage: KeyObservationRegistry { } } - public func removeObserver(forKey key: String) { + public func removeObserver(forKey key: Key) { hybridStorage.removeObserver(forKey: key) } diff --git a/Source/Shared/Storage/StorageAware.swift b/Source/Shared/Storage/StorageAware.swift index 203d6998..ede372fb 100644 --- a/Source/Shared/Storage/StorageAware.swift +++ b/Source/Shared/Storage/StorageAware.swift @@ -2,26 +2,27 @@ import Foundation /// A protocol used for saving and loading from storage public protocol StorageAware { - associatedtype T + associatedtype Key: Hashable + associatedtype Value /** Tries to retrieve the object from the storage. - Parameter key: Unique key to identify the object in the cache - Returns: Cached object or nil if not found */ - func object(forKey key: String) throws -> T + func object(forKey key: Key) throws -> Value /** Get cache entry which includes object with metadata. - Parameter key: Unique key to identify the object in the cache - Returns: Object wrapper with metadata or nil if not found */ - func entry(forKey key: String) throws -> Entry + func entry(forKey key: Key) throws -> Entry /** Removes the object by the given key. - Parameter key: Unique key to identify the object. */ - func removeObject(forKey key: String) throws + func removeObject(forKey key: Key) throws /** Saves passed object. @@ -29,13 +30,13 @@ public protocol StorageAware { - Parameter object: Object that needs to be cached. - Parameter expiry: Overwrite expiry for this object only. */ - func setObject(_ object: T, forKey key: String, expiry: Expiry?) throws + func setObject(_ object: Value, forKey key: Key, expiry: Expiry?) throws /** Check if an object exist by the given key. - Parameter key: Unique key to identify the object. */ - func existsObject(forKey key: String) throws -> Bool + func existsObject(forKey key: Key) throws -> Bool /** Removes all objects from the cache storage. @@ -51,24 +52,24 @@ public protocol StorageAware { Check if an expired object by the given key. - Parameter key: Unique key to identify the object. */ - func isExpiredObject(forKey key: String) throws -> Bool + func isExpiredObject(forKey key: Key) throws -> Bool } public extension StorageAware { - func object(forKey key: String) throws -> T { + func object(forKey key: Key) throws -> Value { return try entry(forKey: key).object } - func existsObject(forKey key: String) throws -> Bool { + func existsObject(forKey key: Key) throws -> Bool { do { - let _: T = try object(forKey: key) + let _: Value = try object(forKey: key) return true } catch { return false } } - func isExpiredObject(forKey key: String) throws -> Bool { + func isExpiredObject(forKey key: Key) throws -> Bool { do { let entry = try self.entry(forKey: key) return entry.expiry.isExpired diff --git a/Source/Shared/Storage/StorageObservationRegistry.swift b/Source/Shared/Storage/StorageObservationRegistry.swift index e2ca6804..abd4927a 100644 --- a/Source/Shared/Storage/StorageObservationRegistry.swift +++ b/Source/Shared/Storage/StorageObservationRegistry.swift @@ -14,7 +14,7 @@ public protocol StorageObservationRegistry { @discardableResult func addStorageObserver( _ observer: O, - closure: @escaping (O, S, StorageChange) -> Void + closure: @escaping (O, S, StorageChange) -> Void ) -> ObservationToken /// Removes all registered key observers @@ -23,14 +23,14 @@ public protocol StorageObservationRegistry { // MARK: - StorageChange -public enum StorageChange: Equatable { - case add(key: String) - case remove(key: String) +public enum StorageChange: Equatable { + case add(key: Key) + case remove(key: Key) case removeAll case removeExpired } -public func == (lhs: StorageChange, rhs: StorageChange) -> Bool { +public func == (lhs: StorageChange, rhs: StorageChange) -> Bool { switch (lhs, rhs) { case (.add(let key1), .add(let key2)), (.remove(let key1), .remove(let key2)): return key1 == key2 diff --git a/Source/Shared/Storage/SyncStorage.swift b/Source/Shared/Storage/SyncStorage.swift index 4b4282a7..65558422 100644 --- a/Source/Shared/Storage/SyncStorage.swift +++ b/Source/Shared/Storage/SyncStorage.swift @@ -3,19 +3,19 @@ import Dispatch /// Manipulate storage in a "all sync" manner. /// Block the current queue until the operation completes. -public class SyncStorage { - public let innerStorage: HybridStorage +public class SyncStorage { + public let innerStorage: HybridStorage public let serialQueue: DispatchQueue - public init(storage: HybridStorage, serialQueue: DispatchQueue) { + public init(storage: HybridStorage, serialQueue: DispatchQueue) { self.innerStorage = storage self.serialQueue = serialQueue } } extension SyncStorage: StorageAware { - public func entry(forKey key: String) throws -> Entry { - var entry: Entry! + public func entry(forKey key: Key) throws -> Entry { + var entry: Entry! try serialQueue.sync { entry = try innerStorage.entry(forKey: key) } @@ -23,13 +23,13 @@ extension SyncStorage: StorageAware { return entry } - public func removeObject(forKey key: String) throws { + public func removeObject(forKey key: Key) throws { try serialQueue.sync { try self.innerStorage.removeObject(forKey: key) } } - public func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws { + public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) throws { try serialQueue.sync { try innerStorage.setObject(object, forKey: key, expiry: expiry) } @@ -49,8 +49,8 @@ extension SyncStorage: StorageAware { } public extension SyncStorage { - func transform(transformer: Transformer) -> SyncStorage { - let storage = SyncStorage( + func transform(transformer: Transformer) -> SyncStorage { + let storage = SyncStorage( storage: innerStorage.transform(transformer: transformer), serialQueue: serialQueue ) From 0fb1ba5e63f8fe12f18ae57207e48750895994cf Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 12:28:34 +0200 Subject: [PATCH 20/73] Update tests --- Tests/iOS/Tests/Library/ObjectConverterTests.swift | 6 +++--- Tests/iOS/Tests/Storage/AsyncStorageTests.swift | 8 ++++---- Tests/iOS/Tests/Storage/DiskStorageTests.swift | 6 +++--- Tests/iOS/Tests/Storage/HybridStorageTests.swift | 8 ++++---- Tests/iOS/Tests/Storage/MemoryStorageTests.swift | 4 ++-- Tests/iOS/Tests/Storage/StorageSupportTests.swift | 8 ++++---- Tests/iOS/Tests/Storage/StorageTests.swift | 12 ++++++------ Tests/iOS/Tests/Storage/SyncStorageTests.swift | 6 +++--- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Tests/iOS/Tests/Library/ObjectConverterTests.swift b/Tests/iOS/Tests/Library/ObjectConverterTests.swift index 7354ca84..70bdecef 100644 --- a/Tests/iOS/Tests/Library/ObjectConverterTests.swift +++ b/Tests/iOS/Tests/Library/ObjectConverterTests.swift @@ -2,12 +2,12 @@ import XCTest @testable import Cache final class JSONDecoderExtensionsTests: XCTestCase { - private var storage: HybridStorage! + private var storage: HybridStorage! override func setUp() { super.setUp() - let memory = MemoryStorage(config: MemoryConfig()) - let disk = try! DiskStorage( + let memory = MemoryStorage(config: MemoryConfig()) + let disk = try! DiskStorage( config: DiskConfig(name: "HybridDisk"), transformer: TransformerFactory.forCodable(ofType: User.self) ) diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index b2a181e7..7ced640d 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -3,14 +3,14 @@ import Dispatch @testable import Cache final class AsyncStorageTests: XCTestCase { - private var storage: AsyncStorage! + private var storage: AsyncStorage! let user = User(firstName: "John", lastName: "Snow") override func setUp() { super.setUp() - let memory = MemoryStorage(config: MemoryConfig()) - let disk = try! DiskStorage(config: DiskConfig(name: "Async Disk"), transformer: TransformerFactory.forCodable(ofType: User.self)) - let hybrid = HybridStorage(memoryStorage: memory, diskStorage: disk) + let memory = MemoryStorage(config: MemoryConfig()) + let disk = try! DiskStorage(config: DiskConfig(name: "Async Disk"), transformer: TransformerFactory.forCodable(ofType: User.self)) + let hybrid = HybridStorage(memoryStorage: memory, diskStorage: disk) storage = AsyncStorage(storage: hybrid, serialQueue: DispatchQueue(label: "Async")) } diff --git a/Tests/iOS/Tests/Storage/DiskStorageTests.swift b/Tests/iOS/Tests/Storage/DiskStorageTests.swift index acd2a29d..a9505b13 100644 --- a/Tests/iOS/Tests/Storage/DiskStorageTests.swift +++ b/Tests/iOS/Tests/Storage/DiskStorageTests.swift @@ -5,12 +5,12 @@ final class DiskStorageTests: XCTestCase { private let key = "youknownothing" private let testObject = User(firstName: "John", lastName: "Snow") private let fileManager = FileManager() - private var storage: DiskStorage! + private var storage: DiskStorage! private let config = DiskConfig(name: "Floppy") override func setUp() { super.setUp() - storage = try! DiskStorage(config: config, transformer: TransformerFactory.forCodable(ofType: User.self)) + storage = try! DiskStorage(config: config, transformer: TransformerFactory.forCodable(ofType: User.self)) } override func tearDown() { @@ -47,7 +47,7 @@ final class DiskStorageTests: XCTestCase { let customConfig = DiskConfig(name: "SSD", directory: url) - storage = try DiskStorage(config: customConfig, transformer: TransformerFactory.forCodable(ofType: User.self)) + storage = try DiskStorage(config: customConfig, transformer: TransformerFactory.forCodable(ofType: User.self)) XCTAssertEqual( storage.path, diff --git a/Tests/iOS/Tests/Storage/HybridStorageTests.swift b/Tests/iOS/Tests/Storage/HybridStorageTests.swift index df2e806d..0262fcb9 100644 --- a/Tests/iOS/Tests/Storage/HybridStorageTests.swift +++ b/Tests/iOS/Tests/Storage/HybridStorageTests.swift @@ -5,13 +5,13 @@ final class HybridStorageTests: XCTestCase { private let cacheName = "WeirdoCache" private let key = "alongweirdkey" private let testObject = User(firstName: "John", lastName: "Targaryen") - private var storage: HybridStorage! + private var storage: HybridStorage! private let fileManager = FileManager() override func setUp() { super.setUp() - let memory = MemoryStorage(config: MemoryConfig()) - let disk = try! DiskStorage(config: DiskConfig(name: "HybridDisk"), transformer: TransformerFactory.forCodable(ofType: User.self)) + let memory = MemoryStorage(config: MemoryConfig()) + let disk = try! DiskStorage(config: DiskConfig(name: "HybridDisk"), transformer: TransformerFactory.forCodable(ofType: User.self)) storage = HybridStorage(memoryStorage: memory, diskStorage: disk) } @@ -160,7 +160,7 @@ final class HybridStorageTests: XCTestCase { // MARK: - Storage observers func testAddStorageObserver() throws { - var changes = [StorageChange]() + var changes = [StorageChange]() storage.addStorageObserver(self) { _, _, change in changes.append(change) } diff --git a/Tests/iOS/Tests/Storage/MemoryStorageTests.swift b/Tests/iOS/Tests/Storage/MemoryStorageTests.swift index 60d8fd41..3b084d94 100644 --- a/Tests/iOS/Tests/Storage/MemoryStorageTests.swift +++ b/Tests/iOS/Tests/Storage/MemoryStorageTests.swift @@ -4,12 +4,12 @@ import XCTest final class MemoryStorageTests: XCTestCase { private let key = "youknownothing" private let testObject = User(firstName: "John", lastName: "Snow") - private var storage: MemoryStorage! + private var storage: MemoryStorage! private let config = MemoryConfig(expiry: .never, countLimit: 10, totalCostLimit: 10) override func setUp() { super.setUp() - storage = MemoryStorage(config: config) + storage = MemoryStorage(config: config) } override func tearDown() { diff --git a/Tests/iOS/Tests/Storage/StorageSupportTests.swift b/Tests/iOS/Tests/Storage/StorageSupportTests.swift index bc328eed..763191e3 100644 --- a/Tests/iOS/Tests/Storage/StorageSupportTests.swift +++ b/Tests/iOS/Tests/Storage/StorageSupportTests.swift @@ -2,13 +2,13 @@ import XCTest @testable import Cache final class StorageSupportTests: XCTestCase { - private var storage: HybridStorage! + private var storage: HybridStorage! override func setUp() { super.setUp() - let memory = MemoryStorage(config: MemoryConfig()) - let disk = try! DiskStorage(config: DiskConfig(name: "PrimitiveDisk"), transformer: TransformerFactory.forCodable(ofType: Bool.self)) - storage = HybridStorage(memoryStorage: memory, diskStorage: disk) + let memory = MemoryStorage(config: MemoryConfig()) + let disk = try! DiskStorage(config: DiskConfig(name: "PrimitiveDisk"), transformer: TransformerFactory.forCodable(ofType: Bool.self)) + storage = HybridStorage(memoryStorage: memory, diskStorage: disk) } override func tearDown() { diff --git a/Tests/iOS/Tests/Storage/StorageTests.swift b/Tests/iOS/Tests/Storage/StorageTests.swift index 018dfc8b..f267f19b 100644 --- a/Tests/iOS/Tests/Storage/StorageTests.swift +++ b/Tests/iOS/Tests/Storage/StorageTests.swift @@ -2,13 +2,13 @@ import XCTest @testable import Cache final class StorageTests: XCTestCase { - private var storage: Storage! + private var storage: Storage! let user = User(firstName: "John", lastName: "Snow") override func setUp() { super.setUp() - storage = try! Storage( + storage = try! Storage( diskConfig: DiskConfig(name: "Thor"), memoryConfig: MemoryConfig(), transformer: TransformerFactory.forCodable(ofType: User.self) @@ -100,7 +100,7 @@ final class StorageTests: XCTestCase { // MARK: - Storage observers func testAddStorageObserver() throws { - var changes = [StorageChange]() + var changes = [StorageChange]() var observer: ObserverMock? = ObserverMock() storage.addStorageObserver(observer!) { _, _, change in @@ -115,7 +115,7 @@ final class StorageTests: XCTestCase { observer = nil try storage.setObject(user, forKey: "user1") - let expectedChanges: [StorageChange] = [ + let expectedChanges: [StorageChange] = [ .add(key: "user1"), .add(key: "user2"), .remove(key: "user1"), @@ -127,8 +127,8 @@ final class StorageTests: XCTestCase { } func testRemoveAllStorageObservers() throws { - var changes1 = [StorageChange]() - var changes2 = [StorageChange]() + var changes1 = [StorageChange]() + var changes2 = [StorageChange]() storage.addStorageObserver(self) { _, _, change in changes1.append(change) diff --git a/Tests/iOS/Tests/Storage/SyncStorageTests.swift b/Tests/iOS/Tests/Storage/SyncStorageTests.swift index 09348385..4c055b33 100644 --- a/Tests/iOS/Tests/Storage/SyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/SyncStorageTests.swift @@ -3,14 +3,14 @@ import Dispatch @testable import Cache final class SyncStorageTests: XCTestCase { - private var storage: SyncStorage! + private var storage: SyncStorage! let user = User(firstName: "John", lastName: "Snow") override func setUp() { super.setUp() - let memory = MemoryStorage(config: MemoryConfig()) - let disk = try! DiskStorage(config: DiskConfig(name: "HybridDisk"), transformer: TransformerFactory.forCodable(ofType: User.self)) + let memory = MemoryStorage(config: MemoryConfig()) + let disk = try! DiskStorage(config: DiskConfig(name: "HybridDisk"), transformer: TransformerFactory.forCodable(ofType: User.self)) let hybridStorage = HybridStorage(memoryStorage: memory, diskStorage: disk) storage = SyncStorage(storage: hybridStorage, serialQueue: DispatchQueue(label: "Sync")) From e215b0bddf51cac19660a7dd5f3e4fef978cf7bb Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 12:28:39 +0200 Subject: [PATCH 21/73] Update xcode project --- Cache.xcodeproj/project.pbxproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 1ad19d9b..fc2f2db5 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 0E79164A250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; + 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; + 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; + 0E79164E250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79164D250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift */; }; BDEDD37D1DBCEB8A007416A6 /* Cache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDEDD3561DBCE5B1007416A6 /* Cache.framework */; }; D21B667C1F6A723C00125DE1 /* DataSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98531F694FFA00CE8F68 /* DataSerializer.swift */; }; D21B667E1F6A723C00125DE1 /* ExpirationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98551F694FFA00CE8F68 /* ExpirationMode.swift */; }; @@ -173,6 +177,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Hasher+constantAccrossExecutions.swift"; sourceTree = ""; }; + 0E79164D250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Hasher+constantAccrossExecutions+Tests.swift"; sourceTree = ""; }; BDEDD3561DBCE5B1007416A6 /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BDEDD3781DBCEB8A007416A6 /* Cache-tvOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Cache-tvOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; D221E5BB20D00D9300BC940E /* MemoryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryStorage.swift; sourceTree = ""; }; @@ -323,6 +329,7 @@ D2CF984F1F694FFA00CE8F68 /* Extensions */ = { isa = PBXGroup; children = ( + 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */, D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */, D2CF98501F694FFA00CE8F68 /* Date+Extensions.swift */, ); @@ -384,6 +391,7 @@ isa = PBXGroup; children = ( D2CF98721F69513800CE8F68 /* Date+ExtensionsTests.swift */, + 0E79164D250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift */, ); path = Extensions; sourceTree = ""; @@ -803,6 +811,7 @@ D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */, D292DAFF1F6A970B0060F614 /* Result.swift in Sources */, D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */, + 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */, D21B668B1F6A723C00125DE1 /* StorageError.swift in Sources */, D5A9D1B921134547005DBD3F /* ObservationToken.swift in Sources */, @@ -848,6 +857,7 @@ D2CF987C1F69513800CE8F68 /* Date+ExtensionsTests.swift in Sources */, D28C9BAC1F67ECD400C180C1 /* TestHelper+iOS.swift in Sources */, D2CF98211F69427C00CE8F68 /* TestHelper.swift in Sources */, + 0E79164E250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift in Sources */, D511464F21147B7C00197DCE /* ObservationTokenTests.swift in Sources */, D2CF987F1F69513800CE8F68 /* ImageWrapperTests.swift in Sources */, D2D4CC1A1FA3166900E4A2D5 /* MD5Tests.swift in Sources */, @@ -889,6 +899,7 @@ D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */, D292DAFE1F6A970B0060F614 /* Result.swift in Sources */, D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */, + 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */, D21B66821F6A723C00125DE1 /* StorageError.swift in Sources */, D5A9D1B821134547005DBD3F /* ObservationToken.swift in Sources */, @@ -942,6 +953,7 @@ D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, D270147C20D107DA003B45C7 /* SyncStorage.swift in Sources */, D2CF98671F694FFA00CE8F68 /* Expiry.swift in Sources */, + 0E79164A250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D270148820D11040003B45C7 /* Storage+Transform.swift in Sources */, D2CF986A1F694FFA00CE8F68 /* StorageError.swift in Sources */, D5A9D1B721134547005DBD3F /* ObservationToken.swift in Sources */, From c92bdd461291fffab3e358742cf46d3694b56932 Mon Sep 17 00:00:00 2001 From: Mathias Quintero Date: Sun, 13 Sep 2020 15:00:50 +0200 Subject: [PATCH 22/73] Fixing image resolution for linux and watchOS --- Source/Shared/Library/ImageWrapper.swift | 2 ++ Source/Shared/Library/TransformerFactory.swift | 2 ++ Source/Shared/Storage/Storage+Transform.swift | 3 +++ 3 files changed, 7 insertions(+) diff --git a/Source/Shared/Library/ImageWrapper.swift b/Source/Shared/Library/ImageWrapper.swift index 65875f91..cc9fd7d7 100644 --- a/Source/Shared/Library/ImageWrapper.swift +++ b/Source/Shared/Library/ImageWrapper.swift @@ -1,5 +1,6 @@ import Foundation +#if os(iOS) || os(tvOS) || os(macOS) public struct ImageWrapper: Codable { public let image: Image @@ -30,3 +31,4 @@ public struct ImageWrapper: Codable { try container.encode(data, forKey: CodingKeys.image) } } +#endif diff --git a/Source/Shared/Library/TransformerFactory.swift b/Source/Shared/Library/TransformerFactory.swift index d6b7b67e..00e4fe9a 100644 --- a/Source/Shared/Library/TransformerFactory.swift +++ b/Source/Shared/Library/TransformerFactory.swift @@ -9,6 +9,7 @@ public class TransformerFactory { return Transformer(toData: toData, fromData: fromData) } + #if os(iOS) || os(tvOS) || os(macOS) public static func forImage() -> Transformer { let toData: (Image) throws -> Data = { image in return try image.cache_toData().unwrapOrThrow(error: StorageError.transformerFail) @@ -20,6 +21,7 @@ public class TransformerFactory { return Transformer(toData: toData, fromData: fromData) } + #endif public static func forCodable(ofType: U.Type) -> Transformer { let toData: (U) throws -> Data = { object in diff --git a/Source/Shared/Storage/Storage+Transform.swift b/Source/Shared/Storage/Storage+Transform.swift index a8db5ddc..494e6afb 100644 --- a/Source/Shared/Storage/Storage+Transform.swift +++ b/Source/Shared/Storage/Storage+Transform.swift @@ -6,10 +6,13 @@ public extension Storage { return storage } + + #if os(iOS) || os(tvOS) || os(macOS) func transformImage() -> Storage { let storage = transform(transformer: TransformerFactory.forImage()) return storage } + #endif func transformCodable(ofType: U.Type) -> Storage { let storage = transform(transformer: TransformerFactory.forCodable(ofType: U.self)) From b879f4da1f9186c7d28d0e89bcaf78860f8c9f49 Mon Sep 17 00:00:00 2001 From: Elvis Date: Sun, 4 Oct 2020 01:41:02 +0200 Subject: [PATCH 23/73] Update project settings --- Cache.xcodeproj/project.pbxproj | 28 ++++++++++--------- .../xcshareddata/xcschemes/Cache-iOS.xcscheme | 24 +++++++--------- .../xcschemes/Cache-macOS.xcscheme | 24 +++++++--------- .../xcschemes/Cache-tvOS.xcscheme | 24 +++++++--------- Tests/Shared/TestHelper.swift | 5 +--- 5 files changed, 46 insertions(+), 59 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 1ad19d9b..18d9d330 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -667,7 +667,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 1030; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Hyper Interaktiv AS"; TargetAttributes = { BDEDD3551DBCE5B1007416A6 = { @@ -1001,7 +1001,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Debug; }; @@ -1026,7 +1026,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Release; }; @@ -1046,7 +1046,7 @@ SDKROOT = appletvos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TVOS_DEPLOYMENT_TARGET = 10.0; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Debug; }; @@ -1064,7 +1064,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; - TVOS_DEPLOYMENT_TARGET = 10.0; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Release; }; @@ -1107,7 +1107,7 @@ INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-Mac"; PRODUCT_NAME = Cache; SDKROOT = macosx; @@ -1129,7 +1129,7 @@ INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-Mac"; PRODUCT_NAME = Cache; SDKROOT = macosx; @@ -1145,7 +1145,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/Mac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-MacTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; @@ -1160,7 +1160,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/Mac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-MacTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; @@ -1190,6 +1190,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -1215,7 +1216,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -1250,6 +1251,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -1269,7 +1271,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -1292,7 +1294,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; @@ -1311,7 +1313,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; diff --git a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme index 46541e5e..3c2c837b 100644 --- a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme +++ b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme @@ -1,6 +1,6 @@ + + + + - - - - - - - - + + + + - - - - - - - - + + + + - - - - - - - - Date: Sun, 4 Oct 2020 02:00:19 +0200 Subject: [PATCH 24/73] Add more support for libraries --- Cache.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index a323f9c8..17e9a643 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -1013,7 +1013,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Debug; }; @@ -1038,7 +1038,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Release; }; @@ -1119,7 +1119,7 @@ INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-Mac"; PRODUCT_NAME = Cache; SDKROOT = macosx; @@ -1141,7 +1141,7 @@ INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-Mac"; PRODUCT_NAME = Cache; SDKROOT = macosx; @@ -1306,7 +1306,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; @@ -1325,7 +1325,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; From f5b1a769f4d168f5def7d8b803b399168924d1dd Mon Sep 17 00:00:00 2001 From: E L V I S <3lvis@users.noreply.github.com> Date: Sun, 4 Oct 2020 02:07:55 +0200 Subject: [PATCH 25/73] Update Cache.podspec --- Cache.podspec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cache.podspec b/Cache.podspec index fb22ae9a..6d31d0b4 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,16 +1,16 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "5.3.0" + s.version = "6.0.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } s.source = { :git => "https://github.com/hyperoslo/Cache.git", :tag => s.version.to_s } s.social_media_url = 'https://twitter.com/hyperoslo' - s.ios.deployment_target = '8.0' - s.osx.deployment_target = '10.9' - s.tvos.deployment_target = '9.2' + s.ios.deployment_target = '11.0' + s.osx.deployment_target = '10.12' + s.tvos.deployment_target = '11.0' s.requires_arc = true s.ios.source_files = 'Source/{iOS,Shared}/**/*' From 1dcf66f5ca5d2e13521eec2009afd3f1aa0635f0 Mon Sep 17 00:00:00 2001 From: Elvis Date: Sun, 4 Oct 2020 02:25:26 +0200 Subject: [PATCH 26/73] Remove swiftlint --- Cache.xcodeproj/project.pbxproj | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 17e9a643..ffcfa91f 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -567,7 +567,6 @@ BDEDD3521DBCE5B1007416A6 /* Frameworks */, BDEDD3531DBCE5B1007416A6 /* Headers */, BDEDD3541DBCE5B1007416A6 /* Resources */, - BDEDD3731DBCE616007416A6 /* ShellScript */, ); buildRules = ( ); @@ -771,22 +770,6 @@ }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - BDEDD3731DBCE616007416A6 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ BDEDD3511DBCE5B1007416A6 /* Sources */ = { isa = PBXSourcesBuildPhase; From c7f4d633049c3bd649a353bad36f6c17e9df085f Mon Sep 17 00:00:00 2001 From: Elvis Date: Sun, 4 Oct 2020 02:39:27 +0200 Subject: [PATCH 27/73] Remove catalyst support --- Cache.xcodeproj/project.pbxproj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index ffcfa91f..05475ed1 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -1211,7 +1211,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -1266,7 +1266,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -1294,6 +1294,8 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -1313,6 +1315,8 @@ PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; From 8c869942f87b6dbc0db20840b216d5e62ab7baaf Mon Sep 17 00:00:00 2001 From: TimFraedrich Date: Sun, 4 Oct 2020 15:09:14 +0000 Subject: [PATCH 28/73] Add DiskStorage size property --- Cache.xcodeproj/project.pbxproj | 16 +++++++++++++ .../Extensions/FileManager+Extensions.swift | 22 +++++++++++++++++ Source/Shared/Extensions/URL+Extensions.swift | 14 +++++++++++ Source/Shared/Storage/DiskStorage.swift | 24 ++++++++----------- Source/Shared/Storage/HybridStorage.swift | 7 ++++++ Source/Shared/Storage/Storage.swift | 7 ++++++ 6 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 Source/Shared/Extensions/FileManager+Extensions.swift create mode 100644 Source/Shared/Extensions/URL+Extensions.swift diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 05475ed1..6e1f7402 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -11,6 +11,12 @@ 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; 0E79164E250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79164D250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift */; }; + 2292AB7B252A14520031F3B9 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */; }; + 2292AB7C252A14520031F3B9 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */; }; + 2292AB7D252A14520031F3B9 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */; }; + 2292AB85252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; + 2292AB86252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; + 2292AB87252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; BDEDD37D1DBCEB8A007416A6 /* Cache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDEDD3561DBCE5B1007416A6 /* Cache.framework */; }; D21B667C1F6A723C00125DE1 /* DataSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98531F694FFA00CE8F68 /* DataSerializer.swift */; }; D21B667E1F6A723C00125DE1 /* ExpirationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98551F694FFA00CE8F68 /* ExpirationMode.swift */; }; @@ -179,6 +185,8 @@ /* Begin PBXFileReference section */ 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Hasher+constantAccrossExecutions.swift"; sourceTree = ""; }; 0E79164D250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Hasher+constantAccrossExecutions+Tests.swift"; sourceTree = ""; }; + 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = ""; }; + 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Extensions.swift"; sourceTree = ""; }; BDEDD3561DBCE5B1007416A6 /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BDEDD3781DBCEB8A007416A6 /* Cache-tvOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Cache-tvOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; D221E5BB20D00D9300BC940E /* MemoryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryStorage.swift; sourceTree = ""; }; @@ -332,6 +340,8 @@ 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */, D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */, D2CF98501F694FFA00CE8F68 /* Date+Extensions.swift */, + 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */, + 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */, ); path = Extensions; sourceTree = ""; @@ -792,10 +802,12 @@ D2D4CC261FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, D27014A720D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */, + 2292AB7D252A14520031F3B9 /* URL+Extensions.swift in Sources */, D292DAFF1F6A970B0060F614 /* Result.swift in Sources */, D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */, 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */, + 2292AB87252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */, D21B668B1F6A723C00125DE1 /* StorageError.swift in Sources */, D5A9D1B921134547005DBD3F /* ObservationToken.swift in Sources */, D270148A20D11040003B45C7 /* Storage+Transform.swift in Sources */, @@ -880,10 +892,12 @@ D2D4CC251FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, D27014A620D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */, + 2292AB7C252A14520031F3B9 /* URL+Extensions.swift in Sources */, D292DAFE1F6A970B0060F614 /* Result.swift in Sources */, D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */, 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */, + 2292AB86252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */, D21B66821F6A723C00125DE1 /* StorageError.swift in Sources */, D5A9D1B821134547005DBD3F /* ObservationToken.swift in Sources */, D270148920D11040003B45C7 /* Storage+Transform.swift in Sources */, @@ -934,10 +948,12 @@ D292DAFD1F6A970B0060F614 /* Result.swift in Sources */, D27014A520D129EB003B45C7 /* TransformerFactory.swift in Sources */, D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, + 2292AB7B252A14520031F3B9 /* URL+Extensions.swift in Sources */, D270147C20D107DA003B45C7 /* SyncStorage.swift in Sources */, D2CF98671F694FFA00CE8F68 /* Expiry.swift in Sources */, 0E79164A250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D270148820D11040003B45C7 /* Storage+Transform.swift in Sources */, + 2292AB85252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */, D2CF986A1F694FFA00CE8F68 /* StorageError.swift in Sources */, D5A9D1B721134547005DBD3F /* ObservationToken.swift in Sources */, D5A138C11EB29BFA00881A20 /* UIImage+Extensions.swift in Sources */, diff --git a/Source/Shared/Extensions/FileManager+Extensions.swift b/Source/Shared/Extensions/FileManager+Extensions.swift new file mode 100644 index 00000000..c0c6c4c0 --- /dev/null +++ b/Source/Shared/Extensions/FileManager+Extensions.swift @@ -0,0 +1,22 @@ + +import Foundation + +extension FileManager { + /** + Calculates the size of the directory at the provided `URL` + - parameter url: the directory url + - returns: the size of the provided directory in bytes + */ + public func sizeOfDirectory(at url: URL) -> Int? { + guard let enumerator = self.enumerator(at: url, includingPropertiesForKeys: [], options: [], errorHandler: { _, _ -> Bool in + return false + }) else { + return nil + } + var size = 0 + for case let url as URL in enumerator { + size += url.fileSize ?? 0 + } + return size + } +} diff --git a/Source/Shared/Extensions/URL+Extensions.swift b/Source/Shared/Extensions/URL+Extensions.swift new file mode 100644 index 00000000..8d7ec491 --- /dev/null +++ b/Source/Shared/Extensions/URL+Extensions.swift @@ -0,0 +1,14 @@ + +import Foundation + +extension URL { + /// Returns the file size of the file at the given `URL` in bytes + var fileSize: Int? { + do { + let file = try self.resourceValues(forKeys: [.totalFileAllocatedSizeKey, .fileAllocatedSizeKey]) + return file.totalFileAllocatedSize ?? file.fileAllocatedSize + } catch { + return nil + } + } +} diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index 76f4cd02..d31f1f4c 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -188,20 +188,6 @@ extension DiskStorage { return "\(path)/\(makeFileName(for: key))" } - /// Calculates total disk cache size. - func totalSize() throws -> UInt64 { - var size: UInt64 = 0 - let contents = try fileManager.contentsOfDirectory(atPath: path) - for pathComponent in contents { - let filePath = NSString(string: path).appendingPathComponent(pathComponent) - let attributes = try fileManager.attributesOfItem(atPath: filePath) - if let fileSize = attributes[.size] as? UInt64 { - size += fileSize - } - } - return size - } - func createDirectory() throws { guard !fileManager.fileExists(atPath: path) else { return @@ -273,3 +259,13 @@ public extension DiskStorage { return storage } } + +public extension DiskStorage { + /// Calculates the total size of the cache directory in bytes. + var totalSize: Int? { + if let directory = URL(string: self.path), let size = self.fileManager.sizeOfDirectory(at: directory) { + return size + } + return nil + } +} diff --git a/Source/Shared/Storage/HybridStorage.swift b/Source/Shared/Storage/HybridStorage.swift index 6a529ccf..61bc60b8 100644 --- a/Source/Shared/Storage/HybridStorage.swift +++ b/Source/Shared/Storage/HybridStorage.swift @@ -165,3 +165,10 @@ extension HybridStorage: KeyObservationRegistry { } } } + +public extension HybridStorage { + /// Returns the total size of the underlying DiskStorage in bytes. + var totalDiskStorageSize: Int? { + return self.diskStorage.totalSize + } +} diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index f3749cc8..816220b8 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -108,3 +108,10 @@ extension Storage: KeyObservationRegistry { hybridStorage.removeAllKeyObservers() } } + +public extension Storage { + /// Returns the total size of the DiskStorage of the underlying HybridStorage in bytes. + var totalDiskStorageSize: Int? { + return self.hybridStorage.diskStorage.totalSize + } +} From 5db17b4a83bfd88488b4e4f80e77648c758f93fa Mon Sep 17 00:00:00 2001 From: E L V I S <3lvis@users.noreply.github.com> Date: Sun, 4 Oct 2020 17:27:46 +0200 Subject: [PATCH 29/73] Update Cache.podspec --- Cache.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cache.podspec b/Cache.podspec index 6d31d0b4..c5a7221f 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "6.0.0" + s.version = "6.1.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } From 4085dcb4543b63ea740d6aea97c9349e8a33b264 Mon Sep 17 00:00:00 2001 From: Elvis Date: Sun, 4 Oct 2020 17:47:56 +0200 Subject: [PATCH 30/73] Update deployment targets --- Cache.xcodeproj/project.pbxproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 6e1f7402..e4968d91 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -1057,6 +1057,7 @@ SDKROOT = appletvos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Debug; @@ -1075,6 +1076,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Release; @@ -1156,7 +1158,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/Mac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-MacTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; @@ -1171,7 +1173,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/Mac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-MacTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; From 9a279c376df29b076915d0e52b2bdb66fb67e469 Mon Sep 17 00:00:00 2001 From: E L V I S <3lvis@users.noreply.github.com> Date: Tue, 6 Oct 2020 19:10:34 +0200 Subject: [PATCH 31/73] Update README.md Fixes #269 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 023ab3e7..04a54a8e 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ let memoryConfig = MemoryConfig(expiry: .never, countLimit: 10, totalCostLimit: let storage = try? Storage( diskConfig: diskConfig, memoryConfig: memoryConfig, - transformer: TransformerFactory.forCodable(ofType: User.self) // Storage + transformer: TransformerFactory.forCodable(ofType: User.self) // Storage ) ``` @@ -86,13 +86,13 @@ All `Storage` now are generic by default, so you can get a type safety experienc If you want to change the type, `Cache` offers `transform` functions, look for `Transformer` and `TransformerFactory` for built-in transformers. ```swift -let storage: Storage = ... +let storage: Storage = ... storage.setObject(superman, forKey: "user") -let imageStorage = storage.transformImage() // Storage +let imageStorage = storage.transformImage() // Storage imageStorage.setObject(image, forKey: "image") -let stringStorage = storage.transformCodable(ofType: String.self) // Storage +let stringStorage = storage.transformCodable(ofType: String.self) // Storage stringStorage.setObject("hello world", forKey: "string") ``` From ed8355b0b0a72faf7c2730a80427ca9f6d287546 Mon Sep 17 00:00:00 2001 From: Colin Humber Date: Thu, 29 Oct 2020 08:20:13 -0600 Subject: [PATCH 32/73] Renamed Result to CacheResult to avoid conflicts with Swift's built-in Result type --- Cache.xcodeproj/project.pbxproj | 16 ++++---- Source/Shared/Library/CacheResult.swift | 16 ++++++++ Source/Shared/Library/Result.swift | 16 -------- Source/Shared/Storage/AsyncStorage.swift | 48 ++++++++++++------------ 4 files changed, 48 insertions(+), 48 deletions(-) create mode 100644 Source/Shared/Library/CacheResult.swift delete mode 100644 Source/Shared/Library/Result.swift diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index e4968d91..1482ccb9 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -101,9 +101,9 @@ D28A1D241F6FFEF60030DF81 /* ObjectConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */; }; D28C9BAC1F67ECD400C180C1 /* TestHelper+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291CDF1C28374800B702C9 /* TestHelper+iOS.swift */; }; D28C9BAF1F67EF8300C180C1 /* UIImage+ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291DA01C28405900B702C9 /* UIImage+ExtensionsTests.swift */; }; - D292DAFD1F6A970B0060F614 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* Result.swift */; }; - D292DAFE1F6A970B0060F614 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* Result.swift */; }; - D292DAFF1F6A970B0060F614 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* Result.swift */; }; + D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; + D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; + D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; D2CF981E1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF981F1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF98201F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; @@ -206,7 +206,7 @@ D27014A420D129EB003B45C7 /* TransformerFactory.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = TransformerFactory.swift; sourceTree = ""; tabWidth = 4; }; D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectConverterTests.swift; sourceTree = ""; }; D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+Extensions.swift"; sourceTree = ""; }; - D292DAFC1F6A970B0060F614 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; + D292DAFC1F6A970B0060F614 /* CacheResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheResult.swift; sourceTree = ""; }; D292DB001F6AA06B0060F614 /* SyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStorageTests.swift; sourceTree = ""; }; D292DB031F6AA0730060F614 /* AsyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncStorageTests.swift; sourceTree = ""; }; D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TestCase+Extensions.swift"; sourceTree = ""; }; @@ -355,7 +355,7 @@ D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */, D2CF98591F694FFA00CE8F68 /* StorageError.swift */, D2CF98861F695B8F00CE8F68 /* Types.swift */, - D292DAFC1F6A970B0060F614 /* Result.swift */, + D292DAFC1F6A970B0060F614 /* CacheResult.swift */, D2D4CC151FA3145000E4A2D5 /* MD5.swift */, D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */, D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */, @@ -803,7 +803,7 @@ D27014A720D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7D252A14520031F3B9 /* URL+Extensions.swift in Sources */, - D292DAFF1F6A970B0060F614 /* Result.swift in Sources */, + D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */, 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -893,7 +893,7 @@ D27014A620D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7C252A14520031F3B9 /* URL+Extensions.swift in Sources */, - D292DAFE1F6A970B0060F614 /* Result.swift in Sources */, + D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */, 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -945,7 +945,7 @@ D270148C20D113EA003B45C7 /* Optional+Extension.swift in Sources */, D2CF98601F694FFA00CE8F68 /* DiskConfig.swift in Sources */, D270147020D1018A003B45C7 /* Transformer.swift in Sources */, - D292DAFD1F6A970B0060F614 /* Result.swift in Sources */, + D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */, D27014A520D129EB003B45C7 /* TransformerFactory.swift in Sources */, D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, 2292AB7B252A14520031F3B9 /* URL+Extensions.swift in Sources */, diff --git a/Source/Shared/Library/CacheResult.swift b/Source/Shared/Library/CacheResult.swift new file mode 100644 index 00000000..2f2d10f2 --- /dev/null +++ b/Source/Shared/Library/CacheResult.swift @@ -0,0 +1,16 @@ +import Foundation + +/// Used for callback in async operations. +public enum CacheResult { + case value(T) + case error(Error) + + public func map(_ transform: (T) -> U) -> CacheResult { + switch self { + case .value(let value): + return CacheResult.value(transform(value)) + case .error(let error): + return CacheResult.error(error) + } + } +} diff --git a/Source/Shared/Library/Result.swift b/Source/Shared/Library/Result.swift deleted file mode 100644 index 4b80f493..00000000 --- a/Source/Shared/Library/Result.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation - -/// Used for callback in async operations. -public enum Result { - case value(T) - case error(Error) - - public func map(_ transform: (T) -> U) -> Result { - switch self { - case .value(let value): - return Result.value(transform(value)) - case .error(let error): - return Result.error(error) - } - } -} diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index 9a119946..5d61d9f2 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -14,34 +14,34 @@ public class AsyncStorage { } extension AsyncStorage { - public func entry(forKey key: Key, completion: @escaping (Result>) -> Void) { + public func entry(forKey key: Key, completion: @escaping (CacheResult>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(Result.error(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { let anEntry = try self.innerStorage.entry(forKey: key) - completion(Result.value(anEntry)) + completion(CacheResult.value(anEntry)) } catch { - completion(Result.error(error)) + completion(CacheResult.error(error)) } } } - public func removeObject(forKey key: Key, completion: @escaping (Result<()>) -> Void) { + public func removeObject(forKey key: Key, completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(Result.error(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.removeObject(forKey: key) - completion(Result.value(())) + completion(CacheResult.value(())) } catch { - completion(Result.error(error)) + completion(CacheResult.error(error)) } } } @@ -50,56 +50,56 @@ extension AsyncStorage { _ object: Value, forKey key: Key, expiry: Expiry? = nil, - completion: @escaping (Result<()>) -> Void) { + completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(Result.error(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.setObject(object, forKey: key, expiry: expiry) - completion(Result.value(())) + completion(CacheResult.value(())) } catch { - completion(Result.error(error)) + completion(CacheResult.error(error)) } } } - public func removeAll(completion: @escaping (Result<()>) -> Void) { + public func removeAll(completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(Result.error(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.removeAll() - completion(Result.value(())) + completion(CacheResult.value(())) } catch { - completion(Result.error(error)) + completion(CacheResult.error(error)) } } } - public func removeExpiredObjects(completion: @escaping (Result<()>) -> Void) { + public func removeExpiredObjects(completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(Result.error(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.removeExpiredObjects() - completion(Result.value(())) + completion(CacheResult.value(())) } catch { - completion(Result.error(error)) + completion(CacheResult.error(error)) } } } - public func object(forKey key: Key, completion: @escaping (Result) -> Void) { - entry(forKey: key, completion: { (result: Result>) in + public func object(forKey key: Key, completion: @escaping (CacheResult) -> Void) { + entry(forKey: key, completion: { (result: CacheResult>) in completion(result.map({ entry in return entry.object })) @@ -108,8 +108,8 @@ extension AsyncStorage { public func existsObject( forKey key: Key, - completion: @escaping (Result) -> Void) { - object(forKey: key, completion: { (result: Result) in + completion: @escaping (CacheResult) -> Void) { + object(forKey: key, completion: { (result: CacheResult) in completion(result.map({ _ in return true })) From f9ba788a26251b48df0c3ba9588f4acf0af93826 Mon Sep 17 00:00:00 2001 From: Artem Garmash Date: Fri, 30 Oct 2020 17:06:00 +0300 Subject: [PATCH 33/73] Remove CacheResult in favor of Swift.Result --- Cache.xcodeproj/project.pbxproj | 8 ---- Source/Shared/Library/CacheResult.swift | 16 ------- Source/Shared/Storage/AsyncStorage.swift | 48 +++++++++---------- .../iOS/Tests/Storage/AsyncStorageTests.swift | 4 +- Tests/iOS/Tests/Storage/StorageTests.swift | 2 +- 5 files changed, 27 insertions(+), 51 deletions(-) delete mode 100644 Source/Shared/Library/CacheResult.swift diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 1482ccb9..4b3d8b5b 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -101,9 +101,6 @@ D28A1D241F6FFEF60030DF81 /* ObjectConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */; }; D28C9BAC1F67ECD400C180C1 /* TestHelper+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291CDF1C28374800B702C9 /* TestHelper+iOS.swift */; }; D28C9BAF1F67EF8300C180C1 /* UIImage+ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291DA01C28405900B702C9 /* UIImage+ExtensionsTests.swift */; }; - D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; - D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; - D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; D2CF981E1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF981F1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF98201F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; @@ -206,7 +203,6 @@ D27014A420D129EB003B45C7 /* TransformerFactory.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = TransformerFactory.swift; sourceTree = ""; tabWidth = 4; }; D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectConverterTests.swift; sourceTree = ""; }; D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+Extensions.swift"; sourceTree = ""; }; - D292DAFC1F6A970B0060F614 /* CacheResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheResult.swift; sourceTree = ""; }; D292DB001F6AA06B0060F614 /* SyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStorageTests.swift; sourceTree = ""; }; D292DB031F6AA0730060F614 /* AsyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncStorageTests.swift; sourceTree = ""; }; D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TestCase+Extensions.swift"; sourceTree = ""; }; @@ -355,7 +351,6 @@ D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */, D2CF98591F694FFA00CE8F68 /* StorageError.swift */, D2CF98861F695B8F00CE8F68 /* Types.swift */, - D292DAFC1F6A970B0060F614 /* CacheResult.swift */, D2D4CC151FA3145000E4A2D5 /* MD5.swift */, D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */, D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */, @@ -803,7 +798,6 @@ D27014A720D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7D252A14520031F3B9 /* URL+Extensions.swift in Sources */, - D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */, 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -893,7 +887,6 @@ D27014A620D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7C252A14520031F3B9 /* URL+Extensions.swift in Sources */, - D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */, 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -945,7 +938,6 @@ D270148C20D113EA003B45C7 /* Optional+Extension.swift in Sources */, D2CF98601F694FFA00CE8F68 /* DiskConfig.swift in Sources */, D270147020D1018A003B45C7 /* Transformer.swift in Sources */, - D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */, D27014A520D129EB003B45C7 /* TransformerFactory.swift in Sources */, D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, 2292AB7B252A14520031F3B9 /* URL+Extensions.swift in Sources */, diff --git a/Source/Shared/Library/CacheResult.swift b/Source/Shared/Library/CacheResult.swift deleted file mode 100644 index 2f2d10f2..00000000 --- a/Source/Shared/Library/CacheResult.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation - -/// Used for callback in async operations. -public enum CacheResult { - case value(T) - case error(Error) - - public func map(_ transform: (T) -> U) -> CacheResult { - switch self { - case .value(let value): - return CacheResult.value(transform(value)) - case .error(let error): - return CacheResult.error(error) - } - } -} diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index 5d61d9f2..032ea08a 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -14,34 +14,34 @@ public class AsyncStorage { } extension AsyncStorage { - public func entry(forKey key: Key, completion: @escaping (CacheResult>) -> Void) { + public func entry(forKey key: Key, completion: @escaping (Result, Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { let anEntry = try self.innerStorage.entry(forKey: key) - completion(CacheResult.value(anEntry)) + completion(.success(anEntry)) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func removeObject(forKey key: Key, completion: @escaping (CacheResult<()>) -> Void) { + public func removeObject(forKey key: Key, completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.removeObject(forKey: key) - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } @@ -50,56 +50,56 @@ extension AsyncStorage { _ object: Value, forKey key: Key, expiry: Expiry? = nil, - completion: @escaping (CacheResult<()>) -> Void) { + completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.setObject(object, forKey: key, expiry: expiry) - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func removeAll(completion: @escaping (CacheResult<()>) -> Void) { + public func removeAll(completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.removeAll() - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func removeExpiredObjects(completion: @escaping (CacheResult<()>) -> Void) { + public func removeExpiredObjects(completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.removeExpiredObjects() - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func object(forKey key: Key, completion: @escaping (CacheResult) -> Void) { - entry(forKey: key, completion: { (result: CacheResult>) in + public func object(forKey key: Key, completion: @escaping (Result) -> Void) { + entry(forKey: key, completion: { (result: Result, Error>) in completion(result.map({ entry in return entry.object })) @@ -108,8 +108,8 @@ extension AsyncStorage { public func existsObject( forKey key: Key, - completion: @escaping (CacheResult) -> Void) { - object(forKey: key, completion: { (result: CacheResult) in + completion: @escaping (Result) -> Void) { + object(forKey: key, completion: { (result: Result) in completion(result.map({ _ in return true })) diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index 7ced640d..63158dc3 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -25,7 +25,7 @@ final class AsyncStorageTests: XCTestCase { storage.setObject(user, forKey: "user", completion: { _ in }) storage.object(forKey: "user", completion: { result in switch result { - case .value(let cachedUser): + case .success(let cachedUser): XCTAssertEqual(cachedUser, self.user) expectation.fulfill() default: @@ -52,7 +52,7 @@ final class AsyncStorageTests: XCTestCase { then("all are removed") { intStorage.existsObject(forKey: "key-99", completion: { result in switch result { - case .value: + case .success: XCTFail() default: expectation.fulfill() diff --git a/Tests/iOS/Tests/Storage/StorageTests.swift b/Tests/iOS/Tests/Storage/StorageTests.swift index f267f19b..80f3f18e 100644 --- a/Tests/iOS/Tests/Storage/StorageTests.swift +++ b/Tests/iOS/Tests/Storage/StorageTests.swift @@ -33,7 +33,7 @@ final class StorageTests: XCTestCase { storage.async.object(forKey: "user", completion: { result in switch result { - case .value(let cachedUser): + case .success(let cachedUser): XCTAssertEqual(cachedUser, self.user) expectation.fulfill() default: From db09aa310d6b97dde22f8d3180e6d954324fbcb8 Mon Sep 17 00:00:00 2001 From: E L V I S <3lvis@users.noreply.github.com> Date: Sat, 31 Oct 2020 17:51:41 +0100 Subject: [PATCH 34/73] Update Cache.podspec --- Cache.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cache.podspec b/Cache.podspec index c5a7221f..c74a7c91 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "6.1.0" + s.version = "7.0.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } From 28acf9a115b5da873c4977bebf2f27ef32d3e634 Mon Sep 17 00:00:00 2001 From: Artem Garmash Date: Fri, 30 Oct 2020 17:06:00 +0300 Subject: [PATCH 35/73] Remove CacheResult in favor of Swift.Result --- Cache.xcodeproj/project.pbxproj | 8 ---- Source/Shared/Library/CacheResult.swift | 16 ------- Source/Shared/Storage/AsyncStorage.swift | 48 +++++++++---------- .../iOS/Tests/Storage/AsyncStorageTests.swift | 4 +- Tests/iOS/Tests/Storage/StorageTests.swift | 2 +- 5 files changed, 27 insertions(+), 51 deletions(-) delete mode 100644 Source/Shared/Library/CacheResult.swift diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 1482ccb9..4b3d8b5b 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -101,9 +101,6 @@ D28A1D241F6FFEF60030DF81 /* ObjectConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */; }; D28C9BAC1F67ECD400C180C1 /* TestHelper+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291CDF1C28374800B702C9 /* TestHelper+iOS.swift */; }; D28C9BAF1F67EF8300C180C1 /* UIImage+ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291DA01C28405900B702C9 /* UIImage+ExtensionsTests.swift */; }; - D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; - D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; - D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; D2CF981E1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF981F1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF98201F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; @@ -206,7 +203,6 @@ D27014A420D129EB003B45C7 /* TransformerFactory.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = TransformerFactory.swift; sourceTree = ""; tabWidth = 4; }; D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectConverterTests.swift; sourceTree = ""; }; D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+Extensions.swift"; sourceTree = ""; }; - D292DAFC1F6A970B0060F614 /* CacheResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheResult.swift; sourceTree = ""; }; D292DB001F6AA06B0060F614 /* SyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStorageTests.swift; sourceTree = ""; }; D292DB031F6AA0730060F614 /* AsyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncStorageTests.swift; sourceTree = ""; }; D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TestCase+Extensions.swift"; sourceTree = ""; }; @@ -355,7 +351,6 @@ D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */, D2CF98591F694FFA00CE8F68 /* StorageError.swift */, D2CF98861F695B8F00CE8F68 /* Types.swift */, - D292DAFC1F6A970B0060F614 /* CacheResult.swift */, D2D4CC151FA3145000E4A2D5 /* MD5.swift */, D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */, D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */, @@ -803,7 +798,6 @@ D27014A720D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7D252A14520031F3B9 /* URL+Extensions.swift in Sources */, - D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */, 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -893,7 +887,6 @@ D27014A620D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7C252A14520031F3B9 /* URL+Extensions.swift in Sources */, - D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */, 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -945,7 +938,6 @@ D270148C20D113EA003B45C7 /* Optional+Extension.swift in Sources */, D2CF98601F694FFA00CE8F68 /* DiskConfig.swift in Sources */, D270147020D1018A003B45C7 /* Transformer.swift in Sources */, - D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */, D27014A520D129EB003B45C7 /* TransformerFactory.swift in Sources */, D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, 2292AB7B252A14520031F3B9 /* URL+Extensions.swift in Sources */, diff --git a/Source/Shared/Library/CacheResult.swift b/Source/Shared/Library/CacheResult.swift deleted file mode 100644 index 2f2d10f2..00000000 --- a/Source/Shared/Library/CacheResult.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation - -/// Used for callback in async operations. -public enum CacheResult { - case value(T) - case error(Error) - - public func map(_ transform: (T) -> U) -> CacheResult { - switch self { - case .value(let value): - return CacheResult.value(transform(value)) - case .error(let error): - return CacheResult.error(error) - } - } -} diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index 5d61d9f2..032ea08a 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -14,34 +14,34 @@ public class AsyncStorage { } extension AsyncStorage { - public func entry(forKey key: Key, completion: @escaping (CacheResult>) -> Void) { + public func entry(forKey key: Key, completion: @escaping (Result, Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { let anEntry = try self.innerStorage.entry(forKey: key) - completion(CacheResult.value(anEntry)) + completion(.success(anEntry)) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func removeObject(forKey key: Key, completion: @escaping (CacheResult<()>) -> Void) { + public func removeObject(forKey key: Key, completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.removeObject(forKey: key) - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } @@ -50,56 +50,56 @@ extension AsyncStorage { _ object: Value, forKey key: Key, expiry: Expiry? = nil, - completion: @escaping (CacheResult<()>) -> Void) { + completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.setObject(object, forKey: key, expiry: expiry) - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func removeAll(completion: @escaping (CacheResult<()>) -> Void) { + public func removeAll(completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.removeAll() - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func removeExpiredObjects(completion: @escaping (CacheResult<()>) -> Void) { + public func removeExpiredObjects(completion: @escaping (Result<(), Error>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(CacheResult.error(StorageError.deallocated)) + completion(.failure(StorageError.deallocated)) return } do { try self.innerStorage.removeExpiredObjects() - completion(CacheResult.value(())) + completion(.success(())) } catch { - completion(CacheResult.error(error)) + completion(.failure(error)) } } } - public func object(forKey key: Key, completion: @escaping (CacheResult) -> Void) { - entry(forKey: key, completion: { (result: CacheResult>) in + public func object(forKey key: Key, completion: @escaping (Result) -> Void) { + entry(forKey: key, completion: { (result: Result, Error>) in completion(result.map({ entry in return entry.object })) @@ -108,8 +108,8 @@ extension AsyncStorage { public func existsObject( forKey key: Key, - completion: @escaping (CacheResult) -> Void) { - object(forKey: key, completion: { (result: CacheResult) in + completion: @escaping (Result) -> Void) { + object(forKey: key, completion: { (result: Result) in completion(result.map({ _ in return true })) diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index 7ced640d..63158dc3 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -25,7 +25,7 @@ final class AsyncStorageTests: XCTestCase { storage.setObject(user, forKey: "user", completion: { _ in }) storage.object(forKey: "user", completion: { result in switch result { - case .value(let cachedUser): + case .success(let cachedUser): XCTAssertEqual(cachedUser, self.user) expectation.fulfill() default: @@ -52,7 +52,7 @@ final class AsyncStorageTests: XCTestCase { then("all are removed") { intStorage.existsObject(forKey: "key-99", completion: { result in switch result { - case .value: + case .success: XCTFail() default: expectation.fulfill() diff --git a/Tests/iOS/Tests/Storage/StorageTests.swift b/Tests/iOS/Tests/Storage/StorageTests.swift index f267f19b..80f3f18e 100644 --- a/Tests/iOS/Tests/Storage/StorageTests.swift +++ b/Tests/iOS/Tests/Storage/StorageTests.swift @@ -33,7 +33,7 @@ final class StorageTests: XCTestCase { storage.async.object(forKey: "user", completion: { result in switch result { - case .value(let cachedUser): + case .success(let cachedUser): XCTAssertEqual(cachedUser, self.user) expectation.fulfill() default: From dcdfd5f8cfdfd3e0f856d73b59d9126715b93a3a Mon Sep 17 00:00:00 2001 From: Elvis Nunez Date: Sun, 1 Nov 2020 09:51:00 +0100 Subject: [PATCH 36/73] Revert "Merge pull request #273 from agarmash/remove-custom-result-type" This reverts commit 43ab355b9e9c6a34e3c813ff6e338aff599f9acb, reversing changes made to 87bf5e0a1d693d9c1213825e017230aedc8836fd. --- Cache.xcodeproj/project.pbxproj | 8 ++++ Source/Shared/Library/CacheResult.swift | 16 +++++++ Source/Shared/Storage/AsyncStorage.swift | 48 +++++++++---------- .../iOS/Tests/Storage/AsyncStorageTests.swift | 4 +- Tests/iOS/Tests/Storage/StorageTests.swift | 2 +- 5 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 Source/Shared/Library/CacheResult.swift diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 4b3d8b5b..1482ccb9 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -101,6 +101,9 @@ D28A1D241F6FFEF60030DF81 /* ObjectConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */; }; D28C9BAC1F67ECD400C180C1 /* TestHelper+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291CDF1C28374800B702C9 /* TestHelper+iOS.swift */; }; D28C9BAF1F67EF8300C180C1 /* UIImage+ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5291DA01C28405900B702C9 /* UIImage+ExtensionsTests.swift */; }; + D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; + D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; + D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292DAFC1F6A970B0060F614 /* CacheResult.swift */; }; D2CF981E1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF981F1F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; D2CF98201F69427C00CE8F68 /* TestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */; }; @@ -203,6 +206,7 @@ D27014A420D129EB003B45C7 /* TransformerFactory.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = TransformerFactory.swift; sourceTree = ""; tabWidth = 4; }; D285143E1F6FFE1F00C674D1 /* ObjectConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectConverterTests.swift; sourceTree = ""; }; D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+Extensions.swift"; sourceTree = ""; }; + D292DAFC1F6A970B0060F614 /* CacheResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheResult.swift; sourceTree = ""; }; D292DB001F6AA06B0060F614 /* SyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStorageTests.swift; sourceTree = ""; }; D292DB031F6AA0730060F614 /* AsyncStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncStorageTests.swift; sourceTree = ""; }; D2CF981B1F69427C00CE8F68 /* TestCase+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TestCase+Extensions.swift"; sourceTree = ""; }; @@ -351,6 +355,7 @@ D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */, D2CF98591F694FFA00CE8F68 /* StorageError.swift */, D2CF98861F695B8F00CE8F68 /* Types.swift */, + D292DAFC1F6A970B0060F614 /* CacheResult.swift */, D2D4CC151FA3145000E4A2D5 /* MD5.swift */, D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */, D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */, @@ -798,6 +803,7 @@ D27014A720D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147E20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7D252A14520031F3B9 /* URL+Extensions.swift in Sources */, + D292DAFF1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B669A1F6A724300125DE1 /* Date+Extensions.swift in Sources */, 0E79164C250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66891F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -887,6 +893,7 @@ D27014A620D129EB003B45C7 /* TransformerFactory.swift in Sources */, D270147D20D107DA003B45C7 /* SyncStorage.swift in Sources */, 2292AB7C252A14520031F3B9 /* URL+Extensions.swift in Sources */, + D292DAFE1F6A970B0060F614 /* CacheResult.swift in Sources */, D21B66991F6A724200125DE1 /* Date+Extensions.swift in Sources */, 0E79164B250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift in Sources */, D21B66801F6A723C00125DE1 /* ImageWrapper.swift in Sources */, @@ -938,6 +945,7 @@ D270148C20D113EA003B45C7 /* Optional+Extension.swift in Sources */, D2CF98601F694FFA00CE8F68 /* DiskConfig.swift in Sources */, D270147020D1018A003B45C7 /* Transformer.swift in Sources */, + D292DAFD1F6A970B0060F614 /* CacheResult.swift in Sources */, D27014A520D129EB003B45C7 /* TransformerFactory.swift in Sources */, D2D4CC241FA3426B00E4A2D5 /* JSONArrayWrapper.swift in Sources */, 2292AB7B252A14520031F3B9 /* URL+Extensions.swift in Sources */, diff --git a/Source/Shared/Library/CacheResult.swift b/Source/Shared/Library/CacheResult.swift new file mode 100644 index 00000000..2f2d10f2 --- /dev/null +++ b/Source/Shared/Library/CacheResult.swift @@ -0,0 +1,16 @@ +import Foundation + +/// Used for callback in async operations. +public enum CacheResult { + case value(T) + case error(Error) + + public func map(_ transform: (T) -> U) -> CacheResult { + switch self { + case .value(let value): + return CacheResult.value(transform(value)) + case .error(let error): + return CacheResult.error(error) + } + } +} diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index 032ea08a..5d61d9f2 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -14,34 +14,34 @@ public class AsyncStorage { } extension AsyncStorage { - public func entry(forKey key: Key, completion: @escaping (Result, Error>) -> Void) { + public func entry(forKey key: Key, completion: @escaping (CacheResult>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(.failure(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { let anEntry = try self.innerStorage.entry(forKey: key) - completion(.success(anEntry)) + completion(CacheResult.value(anEntry)) } catch { - completion(.failure(error)) + completion(CacheResult.error(error)) } } } - public func removeObject(forKey key: Key, completion: @escaping (Result<(), Error>) -> Void) { + public func removeObject(forKey key: Key, completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(.failure(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.removeObject(forKey: key) - completion(.success(())) + completion(CacheResult.value(())) } catch { - completion(.failure(error)) + completion(CacheResult.error(error)) } } } @@ -50,56 +50,56 @@ extension AsyncStorage { _ object: Value, forKey key: Key, expiry: Expiry? = nil, - completion: @escaping (Result<(), Error>) -> Void) { + completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(.failure(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.setObject(object, forKey: key, expiry: expiry) - completion(.success(())) + completion(CacheResult.value(())) } catch { - completion(.failure(error)) + completion(CacheResult.error(error)) } } } - public func removeAll(completion: @escaping (Result<(), Error>) -> Void) { + public func removeAll(completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(.failure(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.removeAll() - completion(.success(())) + completion(CacheResult.value(())) } catch { - completion(.failure(error)) + completion(CacheResult.error(error)) } } } - public func removeExpiredObjects(completion: @escaping (Result<(), Error>) -> Void) { + public func removeExpiredObjects(completion: @escaping (CacheResult<()>) -> Void) { serialQueue.async { [weak self] in guard let `self` = self else { - completion(.failure(StorageError.deallocated)) + completion(CacheResult.error(StorageError.deallocated)) return } do { try self.innerStorage.removeExpiredObjects() - completion(.success(())) + completion(CacheResult.value(())) } catch { - completion(.failure(error)) + completion(CacheResult.error(error)) } } } - public func object(forKey key: Key, completion: @escaping (Result) -> Void) { - entry(forKey: key, completion: { (result: Result, Error>) in + public func object(forKey key: Key, completion: @escaping (CacheResult) -> Void) { + entry(forKey: key, completion: { (result: CacheResult>) in completion(result.map({ entry in return entry.object })) @@ -108,8 +108,8 @@ extension AsyncStorage { public func existsObject( forKey key: Key, - completion: @escaping (Result) -> Void) { - object(forKey: key, completion: { (result: Result) in + completion: @escaping (CacheResult) -> Void) { + object(forKey: key, completion: { (result: CacheResult) in completion(result.map({ _ in return true })) diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index 63158dc3..7ced640d 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -25,7 +25,7 @@ final class AsyncStorageTests: XCTestCase { storage.setObject(user, forKey: "user", completion: { _ in }) storage.object(forKey: "user", completion: { result in switch result { - case .success(let cachedUser): + case .value(let cachedUser): XCTAssertEqual(cachedUser, self.user) expectation.fulfill() default: @@ -52,7 +52,7 @@ final class AsyncStorageTests: XCTestCase { then("all are removed") { intStorage.existsObject(forKey: "key-99", completion: { result in switch result { - case .success: + case .value: XCTFail() default: expectation.fulfill() diff --git a/Tests/iOS/Tests/Storage/StorageTests.swift b/Tests/iOS/Tests/Storage/StorageTests.swift index 80f3f18e..f267f19b 100644 --- a/Tests/iOS/Tests/Storage/StorageTests.swift +++ b/Tests/iOS/Tests/Storage/StorageTests.swift @@ -33,7 +33,7 @@ final class StorageTests: XCTestCase { storage.async.object(forKey: "user", completion: { result in switch result { - case .success(let cachedUser): + case .value(let cachedUser): XCTAssertEqual(cachedUser, self.user) expectation.fulfill() default: From be773e801e72db46aab2d8272cbf3892efada681 Mon Sep 17 00:00:00 2001 From: Artem Garmash Date: Fri, 6 Nov 2020 11:22:40 +0300 Subject: [PATCH 37/73] Update code snippets in readme --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 04a54a8e..99eae0fe 100644 --- a/README.md +++ b/README.md @@ -247,42 +247,42 @@ You access Async APIs via `storage.async`, it is also thread safe, and you can u ```swift storage.async.setObject("Oslo", forKey: "my favorite city") { result in switch result { - case .value: + case .success: print("saved successfully") - case .error(let error): + case .failure(let error): print(error) } } storage.async.object(forKey: "my favorite city") { result in switch result { - case .value(let city): + case .success(let city): print("my favorite city is \(city)") - case .error(let error): + case .failure(let error): print(error) } } storage.async.existsObject(forKey: "my favorite city") { result in - if case .value(let exists) = result, exists { + if case .success(let exists) = result, exists { print("I have a favorite city") } } storage.async.removeAll() { result in switch result { - case .value: + case .success: print("removal completes") - case .error(let error): + case .failure(let error): print(error) } } storage.async.removeExpiredObjects() { result in switch result { - case .value: + case .success: print("removal completes") - case .error(let error): + case .failure(let error): print(error) } } @@ -381,7 +381,7 @@ This is how you perform object converting and saving with `Alamofire` ```swift Alamofire.request("https://gameofthrones.org/mostFavoriteCharacter").responseString { response in do { - let user = try JSONDecoder.decode(response.result.value, to: User.self) + let user = try JSONDecoder.decode(response.result.success, to: User.self) try storage.setObject(user, forKey: "most favorite character") } catch { print(error) From ed4cfaf76c5e98d1d8648a3c37c80aceab4b5cc1 Mon Sep 17 00:00:00 2001 From: Artem Garmash Date: Fri, 6 Nov 2020 11:34:11 +0300 Subject: [PATCH 38/73] Disable parallel test execution --- Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme | 1 - 1 file changed, 1 deletion(-) diff --git a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme index 3c2c837b..fc762f31 100644 --- a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme +++ b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme @@ -39,7 +39,6 @@ Date: Fri, 6 Nov 2020 12:44:04 +0300 Subject: [PATCH 39/73] Update Swift badge to the version 5 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04a54a8e..bfc7ee59 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![License](https://img.shields.io/cocoapods/l/Cache.svg?style=flat)](http://cocoadocs.org/docsets/Cache) [![Platform](https://img.shields.io/cocoapods/p/Cache.svg?style=flat)](http://cocoadocs.org/docsets/Cache) [![Documentation](https://img.shields.io/cocoapods/metrics/doc-percent/Cache.svg?style=flat)](http://cocoadocs.org/docsets/Cache) -![Swift](https://img.shields.io/badge/%20in-swift%204.0-orange.svg) +![Swift](https://img.shields.io/badge/%20in-swift%205-orange.svg) ## Table of Contents From f1c5217faa7cf426748d2920f73c9e4902f94edf Mon Sep 17 00:00:00 2001 From: Quan Tran Date: Wed, 11 Nov 2020 22:30:47 -0600 Subject: [PATCH 40/73] Fix compatibility with Mac Catalyst --- Source/Mac/NSImage+Extensions.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Mac/NSImage+Extensions.swift b/Source/Mac/NSImage+Extensions.swift index 8ebbc9ae..92d6dfc2 100644 --- a/Source/Mac/NSImage+Extensions.swift +++ b/Source/Mac/NSImage+Extensions.swift @@ -1,4 +1,4 @@ -#if canImport(AppKit) +#if canImport(AppKit) && !targetEnvironment(macCatalyst) import AppKit /// Helper UIImage extension. From 27c0a86fdd2eadfdb4b2adf12ac20caf966b49d8 Mon Sep 17 00:00:00 2001 From: Saul Moreno Abril <93sauu@gmail.com> Date: Thu, 12 Nov 2020 14:16:59 +0100 Subject: [PATCH 41/73] Added allKeys and allObjects computed vars for storage with sense --- Source/Shared/Storage/DiskStorage.swift | 4 ++++ Source/Shared/Storage/HybridStorage.swift | 8 ++++++++ Source/Shared/Storage/MemoryStorage.swift | 8 ++++++++ Source/Shared/Storage/Storage.swift | 8 ++++++++ Source/Shared/Storage/StorageAware.swift | 11 +++++++++++ Source/Shared/Storage/SyncStorage.swift | 17 ++++++++++++++++- 6 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index d31f1f4c..d90e9108 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -58,6 +58,10 @@ final public class DiskStorage { } extension DiskStorage: StorageAware { + public var allKeys: [Key] { [] } + + public var allObjects: [Value] { [] } + public func entry(forKey key: Key) throws -> Entry { let filePath = makeFilePath(for: key) let data = try Data(contentsOf: URL(fileURLWithPath: filePath)) diff --git a/Source/Shared/Storage/HybridStorage.swift b/Source/Shared/Storage/HybridStorage.swift index 61bc60b8..385980fe 100644 --- a/Source/Shared/Storage/HybridStorage.swift +++ b/Source/Shared/Storage/HybridStorage.swift @@ -26,6 +26,14 @@ public final class HybridStorage { } extension HybridStorage: StorageAware { + public var allKeys: [Key] { + memoryStorage.allKeys + } + + public var allObjects: [Value] { + memoryStorage.allObjects + } + public func entry(forKey key: Key) throws -> Entry { do { return try memoryStorage.entry(forKey: key) diff --git a/Source/Shared/Storage/MemoryStorage.swift b/Source/Shared/Storage/MemoryStorage.swift index 6ab4b6df..1adc46ff 100644 --- a/Source/Shared/Storage/MemoryStorage.swift +++ b/Source/Shared/Storage/MemoryStorage.swift @@ -31,6 +31,14 @@ public class MemoryStorage: StorageAware { } extension MemoryStorage { + public var allKeys: [Key] { + Array(keys) + } + + public var allObjects: [Value] { + allKeys.compactMap { try? object(forKey: $0) } + } + public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) { let capsule = MemoryCapsule(value: object, expiry: .date(expiry?.date ?? config.expiry.date)) cache.setObject(capsule, forKey: WrappedKey(key)) diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index 816220b8..e2d7c69c 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -43,6 +43,14 @@ public final class Storage { } extension Storage: StorageAware { + public var allKeys: [Key] { + self.syncStorage.allKeys + } + + public var allObjects: [Value] { + self.syncStorage.allObjects + } + public func entry(forKey key: Key) throws -> Entry { return try self.syncStorage.entry(forKey: key) } diff --git a/Source/Shared/Storage/StorageAware.swift b/Source/Shared/Storage/StorageAware.swift index ede372fb..cbbb8ce2 100644 --- a/Source/Shared/Storage/StorageAware.swift +++ b/Source/Shared/Storage/StorageAware.swift @@ -4,6 +4,17 @@ import Foundation public protocol StorageAware { associatedtype Key: Hashable associatedtype Value + + /** + Get all keys in the storage + */ + var allKeys: [Key] { get } + + /** + Get all objects from the storage + */ + var allObjects: [Value] { get } + /** Tries to retrieve the object from the storage. - Parameter key: Unique key to identify the object in the cache diff --git a/Source/Shared/Storage/SyncStorage.swift b/Source/Shared/Storage/SyncStorage.swift index 65558422..51d15f0e 100644 --- a/Source/Shared/Storage/SyncStorage.swift +++ b/Source/Shared/Storage/SyncStorage.swift @@ -14,12 +14,27 @@ public class SyncStorage { } extension SyncStorage: StorageAware { + public var allKeys: [Key] { + var keys: [Key]! + serialQueue.sync { + keys = self.innerStorage.allKeys + } + return keys + } + + public var allObjects: [Value] { + var objects: [Value]! + serialQueue.sync { + objects = self.innerStorage.allObjects + } + return objects + } + public func entry(forKey key: Key) throws -> Entry { var entry: Entry! try serialQueue.sync { entry = try innerStorage.entry(forKey: key) } - return entry } From fe15b7cdf7266d22aa399f0c70cc3db733144970 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 17 Jan 2021 15:27:05 -0500 Subject: [PATCH 42/73] DiskStorage file URL handling improvements --- Source/Shared/Storage/DiskStorage.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index d90e9108..ca4db9a1 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -64,7 +64,7 @@ extension DiskStorage: StorageAware { public func entry(forKey key: Key) throws -> Entry { let filePath = makeFilePath(for: key) - let data = try Data(contentsOf: URL(fileURLWithPath: filePath)) + let data = try Data(contentsOf: URL(fileURLWithPath: filePath, isDirectory: false)) let attributes = try fileManager.attributesOfItem(atPath: filePath) let object = try transformer.fromData(data) @@ -99,7 +99,7 @@ extension DiskStorage: StorageAware { } public func removeExpiredObjects() throws { - let storageURL = URL(fileURLWithPath: path) + let storageURL = URL(fileURLWithPath: path, isDirectory: true) let resourceKeys: [URLResourceKey] = [ .isDirectoryKey, .contentModificationDateKey, @@ -167,7 +167,7 @@ extension DiskStorage { */ func makeFileName(for key: Key) -> String { if let key = key as? String { - let fileExtension = URL(fileURLWithPath: key).pathExtension + let fileExtension = (key as NSString).pathExtension let fileName = MD5(key) switch fileExtension.isEmpty { From 3116f50bdc5ec2dd2188f6193497e51a8f62d817 Mon Sep 17 00:00:00 2001 From: Igor Skovorodkin Date: Thu, 13 May 2021 16:03:07 +0300 Subject: [PATCH 43/73] watchOS support --- Cache.podspec | 2 + Cache.xcodeproj/project.pbxproj | 208 ++++++++++++++++++ Source/Shared/Configuration/DiskConfig.swift | 2 +- Source/Shared/Library/ImageWrapper.swift | 2 +- .../Shared/Library/TransformerFactory.swift | 2 +- Source/Shared/Library/Types.swift | 2 +- Source/Shared/Storage/DiskStorage.swift | 2 +- Source/Shared/Storage/Storage+Transform.swift | 2 +- SupportFiles/watchOS/Info.plist | 22 ++ 9 files changed, 238 insertions(+), 6 deletions(-) create mode 100644 SupportFiles/watchOS/Info.plist diff --git a/Cache.podspec b/Cache.podspec index 6d31d0b4..9dfb6483 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -11,11 +11,13 @@ Pod::Spec.new do |s| s.ios.deployment_target = '11.0' s.osx.deployment_target = '10.12' s.tvos.deployment_target = '11.0' + s.watchos.deployment_target = '5.0' s.requires_arc = true s.ios.source_files = 'Source/{iOS,Shared}/**/*' s.osx.source_files = 'Source/{Mac,Shared}/**/*' s.tvos.source_files = 'Source/{iOS,Shared}/**/*' + s.watchos.source_files = 'Source/{iOS,Shared}/**/*' s.frameworks = 'Foundation' s.swift_version = '5.0' diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 05475ed1..64d3441a 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -150,6 +150,40 @@ D5A9D1C321144B65005DBD3F /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; D5A9D1C421144B65005DBD3F /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; D5A9D1C521144B65005DBD3F /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; + F812FB77264D57BC00D179F5 /* MemoryConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF984E1F694FFA00CE8F68 /* MemoryConfig.swift */; }; + F812FB78264D57BC00D179F5 /* DiskConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF984D1F694FFA00CE8F68 /* DiskConfig.swift */; }; + F812FB79264D57BC00D179F5 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98501F694FFA00CE8F68 /* Date+Extensions.swift */; }; + F812FB7A264D57BC00D179F5 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; + F812FB7B264D57BC00D179F5 /* JSONDecoder+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */; }; + F812FB7C264D57BC00D179F5 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */; }; + F812FB7D264D57BC00D179F5 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; + F812FB7E264D57C300D179F5 /* TransformerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27014A420D129EB003B45C7 /* TransformerFactory.swift */; }; + F812FB7F264D57C300D179F5 /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148B20D113EA003B45C7 /* Optional+Extension.swift */; }; + F812FB80264D57C300D179F5 /* JSONDictionaryWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */; }; + F812FB81264D57C300D179F5 /* ExpirationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98551F694FFA00CE8F68 /* ExpirationMode.swift */; }; + F812FB82264D57C300D179F5 /* ImageWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */; }; + F812FB83264D57C300D179F5 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98861F695B8F00CE8F68 /* Types.swift */; }; + F812FB84264D57C300D179F5 /* StorageError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98591F694FFA00CE8F68 /* StorageError.swift */; }; + F812FB85264D57C300D179F5 /* JSONArrayWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */; }; + F812FB86264D57C300D179F5 /* TypeWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148F20D1251E003B45C7 /* TypeWrapper.swift */; }; + F812FB87264D57C300D179F5 /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1B621134547005DBD3F /* ObservationToken.swift */; }; + F812FB88264D57C300D179F5 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5BF20D00DCC00BC940E /* Entry.swift */; }; + F812FB89264D57C300D179F5 /* MemoryCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270149320D125AC003B45C7 /* MemoryCapsule.swift */; }; + F812FB8A264D57C300D179F5 /* DataSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98531F694FFA00CE8F68 /* DataSerializer.swift */; }; + F812FB8B264D57C300D179F5 /* Expiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98561F694FFA00CE8F68 /* Expiry.swift */; }; + F812FB8C264D57C300D179F5 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC151FA3145000E4A2D5 /* MD5.swift */; }; + F812FB8D264D57C300D179F5 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270146F20D1018A003B45C7 /* Transformer.swift */; }; + F812FB8E264D57C800D179F5 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147F20D10982003B45C7 /* Storage.swift */; }; + F812FB8F264D57C800D179F5 /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; + F812FB90264D57C800D179F5 /* HybridStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147720D1046A003B45C7 /* HybridStorage.swift */; }; + F812FB91264D57C800D179F5 /* SyncStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147B20D107DA003B45C7 /* SyncStorage.swift */; }; + F812FB92264D57C800D179F5 /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5BB20D00D9300BC940E /* MemoryStorage.swift */; }; + F812FB93264D57C800D179F5 /* KeyObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51146522118337500197DCE /* KeyObservationRegistry.swift */; }; + F812FB94264D57C800D179F5 /* AsyncStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148320D10E76003B45C7 /* AsyncStorage.swift */; }; + F812FB95264D57C800D179F5 /* Storage+Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148720D11040003B45C7 /* Storage+Transform.swift */; }; + F812FB96264D57C800D179F5 /* DiskStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5C320D00DDB00BC940E /* DiskStorage.swift */; }; + F812FB97264D57C800D179F5 /* StorageAware.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147320D101F3003B45C7 /* StorageAware.swift */; }; + F812FB98264D57CC00D179F5 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A138C01EB29BFA00881A20 /* UIImage+Extensions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -245,6 +279,9 @@ D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageObservationRegistry.swift; sourceTree = ""; }; D5DC59E01C20593E003BD79B /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EBAACA991FBC369300FA206E /* SimpleStorage.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SimpleStorage.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + F812FB6F264D579E00D179F5 /* Cache_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F812FB71264D579E00D179F5 /* Cache_watchOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Cache_watchOS.h; sourceTree = ""; }; + F812FB72264D579E00D179F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -293,6 +330,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F812FB6C264D579E00D179F5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -503,6 +547,7 @@ D5643E341C43F2CC00582E17 /* Playgrounds */, D5291C081C28220B00B702C9 /* Source */, D5DC59FA1C205AC9003BD79B /* Tests */, + F812FB70264D579E00D179F5 /* Cache-watchOS */, D5DC59E11C20593E003BD79B /* Products */, ); indentWidth = 4; @@ -518,6 +563,7 @@ D5291D691C283B5400B702C9 /* Cache-Mac-Tests.xctest */, BDEDD3561DBCE5B1007416A6 /* Cache.framework */, BDEDD3781DBCEB8A007416A6 /* Cache-tvOS-Tests.xctest */, + F812FB6F264D579E00D179F5 /* Cache_watchOS.framework */, ); name = Products; sourceTree = ""; @@ -532,6 +578,15 @@ path = Tests; sourceTree = ""; }; + F812FB70264D579E00D179F5 /* Cache-watchOS */ = { + isa = PBXGroup; + children = ( + F812FB71264D579E00D179F5 /* Cache_watchOS.h */, + F812FB72264D579E00D179F5 /* Info.plist */, + ); + path = "Cache-watchOS"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -556,6 +611,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F812FB6A264D579E00D179F5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -667,6 +729,24 @@ productReference = D5DC59E01C20593E003BD79B /* Cache.framework */; productType = "com.apple.product-type.framework"; }; + F812FB6E264D579E00D179F5 /* Cache-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = F812FB76264D579E00D179F5 /* Build configuration list for PBXNativeTarget "Cache-watchOS" */; + buildPhases = ( + F812FB6A264D579E00D179F5 /* Headers */, + F812FB6B264D579E00D179F5 /* Sources */, + F812FB6C264D579E00D179F5 /* Frameworks */, + F812FB6D264D579E00D179F5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Cache-watchOS"; + productName = "Cache-watchOS"; + productReference = F812FB6F264D579E00D179F5 /* Cache_watchOS.framework */; + productType = "com.apple.product-type.framework"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -700,6 +780,10 @@ CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; + F812FB6E264D579E00D179F5 = { + CreatedOnToolsVersion = 12.5; + ProvisioningStyle = Manual; + }; }; }; buildConfigurationList = D5DC59DA1C20593E003BD79B /* Build configuration list for PBXProject "Cache" */; @@ -721,6 +805,7 @@ D5291D681C283B5400B702C9 /* Cache-Mac-Tests */, BDEDD3551DBCE5B1007416A6 /* Cache-tvOS */, BDEDD3771DBCEB8A007416A6 /* Cache-tvOS-Tests */, + F812FB6E264D579E00D179F5 /* Cache-watchOS */, ); }; /* End PBXProject section */ @@ -768,6 +853,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F812FB6D264D579E00D179F5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -953,6 +1045,47 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F812FB6B264D579E00D179F5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F812FB95264D57C800D179F5 /* Storage+Transform.swift in Sources */, + F812FB81264D57C300D179F5 /* ExpirationMode.swift in Sources */, + F812FB82264D57C300D179F5 /* ImageWrapper.swift in Sources */, + F812FB78264D57BC00D179F5 /* DiskConfig.swift in Sources */, + F812FB8A264D57C300D179F5 /* DataSerializer.swift in Sources */, + F812FB8D264D57C300D179F5 /* Transformer.swift in Sources */, + F812FB8E264D57C800D179F5 /* Storage.swift in Sources */, + F812FB7D264D57BC00D179F5 /* FileManager+Extensions.swift in Sources */, + F812FB8B264D57C300D179F5 /* Expiry.swift in Sources */, + F812FB92264D57C800D179F5 /* MemoryStorage.swift in Sources */, + F812FB7C264D57BC00D179F5 /* URL+Extensions.swift in Sources */, + F812FB80264D57C300D179F5 /* JSONDictionaryWrapper.swift in Sources */, + F812FB96264D57C800D179F5 /* DiskStorage.swift in Sources */, + F812FB88264D57C300D179F5 /* Entry.swift in Sources */, + F812FB89264D57C300D179F5 /* MemoryCapsule.swift in Sources */, + F812FB8C264D57C300D179F5 /* MD5.swift in Sources */, + F812FB7B264D57BC00D179F5 /* JSONDecoder+Extensions.swift in Sources */, + F812FB91264D57C800D179F5 /* SyncStorage.swift in Sources */, + F812FB87264D57C300D179F5 /* ObservationToken.swift in Sources */, + F812FB97264D57C800D179F5 /* StorageAware.swift in Sources */, + F812FB85264D57C300D179F5 /* JSONArrayWrapper.swift in Sources */, + F812FB7F264D57C300D179F5 /* Optional+Extension.swift in Sources */, + F812FB8F264D57C800D179F5 /* StorageObservationRegistry.swift in Sources */, + F812FB83264D57C300D179F5 /* Types.swift in Sources */, + F812FB90264D57C800D179F5 /* HybridStorage.swift in Sources */, + F812FB77264D57BC00D179F5 /* MemoryConfig.swift in Sources */, + F812FB93264D57C800D179F5 /* KeyObservationRegistry.swift in Sources */, + F812FB84264D57C300D179F5 /* StorageError.swift in Sources */, + F812FB7A264D57BC00D179F5 /* Hasher+constantAccrossExecutions.swift in Sources */, + F812FB94264D57C800D179F5 /* AsyncStorage.swift in Sources */, + F812FB7E264D57C300D179F5 /* TransformerFactory.swift in Sources */, + F812FB98264D57CC00D179F5 /* UIImage+Extensions.swift in Sources */, + F812FB79264D57BC00D179F5 /* Date+Extensions.swift in Sources */, + F812FB86264D57C300D179F5 /* TypeWrapper.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -1320,6 +1453,72 @@ }; name = Release; }; + F812FB74264D579E00D179F5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/watchOS/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-watchOS"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.0; + }; + name = Debug; + }; + F812FB75264D579E00D179F5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/watchOS/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-watchOS"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1386,6 +1585,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F812FB76264D579E00D179F5 /* Build configuration list for PBXNativeTarget "Cache-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F812FB74264D579E00D179F5 /* Debug */, + F812FB75264D579E00D179F5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = D5DC59D71C20593E003BD79B /* Project object */; diff --git a/Source/Shared/Configuration/DiskConfig.swift b/Source/Shared/Configuration/DiskConfig.swift index 3d0a01c5..e57212a3 100644 --- a/Source/Shared/Configuration/DiskConfig.swift +++ b/Source/Shared/Configuration/DiskConfig.swift @@ -10,7 +10,7 @@ public struct DiskConfig { public let maxSize: UInt /// A folder to store the disk cache contents. Defaults to a prefixed directory in Caches if nil public let directory: URL? - #if os(iOS) || os(tvOS) + #if os(iOS) || os(tvOS) || os(watchOS) /// Data protection is used to store files in an encrypted format on disk and to decrypt them on demand. /// Support only on iOS and tvOS. public let protectionType: FileProtectionType? diff --git a/Source/Shared/Library/ImageWrapper.swift b/Source/Shared/Library/ImageWrapper.swift index cc9fd7d7..5bc0cdde 100644 --- a/Source/Shared/Library/ImageWrapper.swift +++ b/Source/Shared/Library/ImageWrapper.swift @@ -1,6 +1,6 @@ import Foundation -#if os(iOS) || os(tvOS) || os(macOS) +#if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) public struct ImageWrapper: Codable { public let image: Image diff --git a/Source/Shared/Library/TransformerFactory.swift b/Source/Shared/Library/TransformerFactory.swift index 00e4fe9a..e10a212e 100644 --- a/Source/Shared/Library/TransformerFactory.swift +++ b/Source/Shared/Library/TransformerFactory.swift @@ -9,7 +9,7 @@ public class TransformerFactory { return Transformer(toData: toData, fromData: fromData) } - #if os(iOS) || os(tvOS) || os(macOS) + #if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) public static func forImage() -> Transformer { let toData: (Image) throws -> Data = { image in return try image.cache_toData().unwrapOrThrow(error: StorageError.transformerFail) diff --git a/Source/Shared/Library/Types.swift b/Source/Shared/Library/Types.swift index 81e7a301..caf74563 100644 --- a/Source/Shared/Library/Types.swift +++ b/Source/Shared/Library/Types.swift @@ -1,4 +1,4 @@ -#if os(iOS) || os(tvOS) +#if os(iOS) || os(tvOS) || os(watchOS) import UIKit public typealias Image = UIImage #elseif os(watchOS) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index 76f4cd02..78adad54 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -40,7 +40,7 @@ final public class DiskStorage { try createDirectory() // protection - #if os(iOS) || os(tvOS) + #if os(iOS) || os(tvOS) || os(watchOS) if let protectionType = config.protectionType { try setDirectoryAttributes([ FileAttributeKey.protectionKey: protectionType diff --git a/Source/Shared/Storage/Storage+Transform.swift b/Source/Shared/Storage/Storage+Transform.swift index 494e6afb..af1bc366 100644 --- a/Source/Shared/Storage/Storage+Transform.swift +++ b/Source/Shared/Storage/Storage+Transform.swift @@ -7,7 +7,7 @@ public extension Storage { } - #if os(iOS) || os(tvOS) || os(macOS) + #if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) func transformImage() -> Storage { let storage = transform(transformer: TransformerFactory.forImage()) return storage diff --git a/SupportFiles/watchOS/Info.plist b/SupportFiles/watchOS/Info.plist new file mode 100644 index 00000000..37f13eb0 --- /dev/null +++ b/SupportFiles/watchOS/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + From 5766a61ec509eac4c8081d109dacd2ca41391f4a Mon Sep 17 00:00:00 2001 From: Roman Blum Date: Wed, 2 Jun 2021 10:01:43 +0200 Subject: [PATCH 44/73] Update Hasher+constantAccrossExecutions.swift Add original license to file header in order to comply to FOSS --- .../Hasher+constantAccrossExecutions.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift b/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift index 1406a54f..37d0feee 100644 --- a/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift +++ b/Source/Shared/Extensions/Hasher+constantAccrossExecutions.swift @@ -1,3 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +/// This file implements SipHash-2-4 and SipHash-1-3 +/// (https://131002.net/siphash/). +/// +/// This file is based on the reference C implementation, which was released +/// to public domain by: +/// +/// * Jean-Philippe Aumasson +/// * Daniel J. Bernstein +//===----------------------------------------------------------------------===// import Foundation From 9efca9d8017c6c866ac146f82a1637c82c50755f Mon Sep 17 00:00:00 2001 From: Alexey Ivashko Date: Tue, 8 Jun 2021 12:31:12 +0300 Subject: [PATCH 45/73] Fix SPM warning in Xcode 13b1 --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index c6fcee49..c167e646 100644 --- a/Package.swift +++ b/Package.swift @@ -13,8 +13,8 @@ let package = Package( targets: [ .target( name: "Cache", - path: "Source", - exclude: ["Library/ImageWrapper.swift"]), + path: "Source" + ), .testTarget( name: "CacheTests", dependencies: ["Cache"], From 033457ce946725e7d8c9ed47fbd19c5f74282312 Mon Sep 17 00:00:00 2001 From: Abdullah Alhaider Date: Wed, 8 Dec 2021 13:01:51 +0500 Subject: [PATCH 46/73] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 137c354f..45afb49e 100644 --- a/README.md +++ b/README.md @@ -391,7 +391,7 @@ Alamofire.request("https://gameofthrones.org/mostFavoriteCharacter").responseStr ## What about images -If you want to load image into `UIImageView` or `NSImageView`, then we also have a nice gift for you. It's called [Imaginary](https://github.com/hyperoslo/Imaginary) and uses `Cache` under the hood to make you life easier when it comes to working with remote images. +If you want to load image into `UIImageView` or `NSImageView`, then we also have a nice gift for you. It's called [Imaginary](https://github.com/hyperoslo/Imaginary) and uses `Cache` under the hood to make your life easier when it comes to working with remote images. ## Installation From 08de6c481cabc4ca06f4cbbbbcb4cfad15dcede3 Mon Sep 17 00:00:00 2001 From: Maxb Date: Fri, 27 May 2022 17:10:09 +0800 Subject: [PATCH 47/73] remove older files not recent --- Source/Shared/Storage/DiskStorage.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index ca4db9a1..0eca4b88 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -217,7 +217,7 @@ extension DiskStorage { let sortedFiles = objects.sorted { if let time1 = $0.resourceValues.contentModificationDate?.timeIntervalSinceReferenceDate, let time2 = $1.resourceValues.contentModificationDate?.timeIntervalSinceReferenceDate { - return time1 > time2 + return time1 < time2 } else { return false } From 33a693c45e8ad1db4e7be59c6181f076195fc34c Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Sun, 14 Aug 2022 13:48:44 -0400 Subject: [PATCH 48/73] Add objectExists to replace existsObject --- Source/Shared/Storage/AsyncStorage.swift | 11 +++++++++++ Source/Shared/Storage/StorageAware.swift | 16 ++++++++++++++++ Tests/iOS/Tests/Storage/AsyncStorageTests.swift | 2 +- Tests/iOS/Tests/Storage/SyncStorageTests.swift | 4 ++-- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index 032ea08a..4f1c1b04 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -106,6 +106,7 @@ extension AsyncStorage { }) } + @available(*, deprecated, renamed: "objectExists(forKey:completion:)") public func existsObject( forKey key: Key, completion: @escaping (Result) -> Void) { @@ -115,6 +116,16 @@ extension AsyncStorage { })) }) } + + public func objectExists( + forKey key: Key, + completion: @escaping (Result) -> Void) { + object(forKey: key, completion: { (result: Result) in + completion(result.map({ _ in + return true + })) + }) + } } public extension AsyncStorage { diff --git a/Source/Shared/Storage/StorageAware.swift b/Source/Shared/Storage/StorageAware.swift index cbbb8ce2..2b589416 100644 --- a/Source/Shared/Storage/StorageAware.swift +++ b/Source/Shared/Storage/StorageAware.swift @@ -47,8 +47,15 @@ public protocol StorageAware { Check if an object exist by the given key. - Parameter key: Unique key to identify the object. */ + @available(*, deprecated, renamed: "objectExists(forKey:)") func existsObject(forKey key: Key) throws -> Bool + /** + Check if an object exist by the given key. + - Parameter key: Unique key to identify the object. + */ + func objectExists(forKey key: Key) -> Bool + /** Removes all objects from the cache storage. */ @@ -80,6 +87,15 @@ public extension StorageAware { } } + func objectExists(forKey key: Key) -> Bool { + do { + let _: Value = try object(forKey: key) + return true + } catch { + return false + } + } + func isExpiredObject(forKey key: Key) throws -> Bool { do { let entry = try self.entry(forKey: key) diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index 63158dc3..1251d152 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -50,7 +50,7 @@ final class AsyncStorageTests: XCTestCase { } then("all are removed") { - intStorage.existsObject(forKey: "key-99", completion: { result in + intStorage.objectExists(forKey: "key-99", completion: { result in switch result { case .success: XCTFail() diff --git a/Tests/iOS/Tests/Storage/SyncStorageTests.swift b/Tests/iOS/Tests/Storage/SyncStorageTests.swift index 4c055b33..8d31f820 100644 --- a/Tests/iOS/Tests/Storage/SyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/SyncStorageTests.swift @@ -40,8 +40,8 @@ final class SyncStorageTests: XCTestCase { try intStorage.removeAll() } - try then("all are removed") { - XCTAssertFalse(try intStorage.existsObject(forKey: "key-99")) + then("all are removed") { + XCTAssertFalse(intStorage.objectExists(forKey: "key-99")) } } } From de764f82582d5bf55a86f4ee798bdb856403f492 Mon Sep 17 00:00:00 2001 From: pareshios Date: Tue, 2 May 2023 16:54:49 +0530 Subject: [PATCH 49/73] feat: Added support to remove only in memory cache --- Source/Shared/Storage/DiskStorage.swift | 2 ++ Source/Shared/Storage/HybridStorage.swift | 5 +++++ Source/Shared/Storage/MemoryStorage.swift | 5 +++++ Source/Shared/Storage/Storage.swift | 4 ++++ Source/Shared/Storage/StorageAware.swift | 5 +++++ Source/Shared/Storage/StorageObservationRegistry.swift | 3 ++- Source/Shared/Storage/SyncStorage.swift | 7 +++++++ 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index ca4db9a1..b0bf9e37 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -145,6 +145,8 @@ extension DiskStorage: StorageAware { // Remove objects if storage size exceeds max size try removeResourceObjects(resourceObjects, totalSize: totalSize) } + + public func removeInMemoryObject(forKey key: Key) throws { } } extension DiskStorage { diff --git a/Source/Shared/Storage/HybridStorage.swift b/Source/Shared/Storage/HybridStorage.swift index 385980fe..98448035 100644 --- a/Source/Shared/Storage/HybridStorage.swift +++ b/Source/Shared/Storage/HybridStorage.swift @@ -51,6 +51,11 @@ extension HybridStorage: StorageAware { notifyStorageObservers(about: .remove(key: key)) } + + public func removeInMemoryObject(forKey key: Key) throws { + memoryStorage.removeObject(forKey: key) + notifyStorageObservers(about: .removeInMemory(key: key)) + } public func setObject(_ object: Value, forKey key: Key, expiry: Expiry? = nil) throws { var keyChange: KeyChange? diff --git a/Source/Shared/Storage/MemoryStorage.swift b/Source/Shared/Storage/MemoryStorage.swift index 1adc46ff..567bf317 100644 --- a/Source/Shared/Storage/MemoryStorage.swift +++ b/Source/Shared/Storage/MemoryStorage.swift @@ -67,6 +67,11 @@ extension MemoryStorage { cache.removeObject(forKey: WrappedKey(key)) keys.remove(key) } + + public func removeInMemoryObject(forKey key: Key) throws { + cache.removeObject(forKey: WrappedKey(key)) + keys.remove(key) + } public func entry(forKey key: Key) throws -> Entry { guard let capsule = cache.object(forKey: WrappedKey(key)) else { diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index e2d7c69c..12b567f1 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -43,6 +43,10 @@ public final class Storage { } extension Storage: StorageAware { + public func removeInMemoryObject(forKey key: Key) throws { + try self.syncStorage.removeInMemoryObject(forKey: key) + } + public var allKeys: [Key] { self.syncStorage.allKeys } diff --git a/Source/Shared/Storage/StorageAware.swift b/Source/Shared/Storage/StorageAware.swift index 2b589416..6ab7b3f5 100644 --- a/Source/Shared/Storage/StorageAware.swift +++ b/Source/Shared/Storage/StorageAware.swift @@ -71,6 +71,11 @@ public protocol StorageAware { - Parameter key: Unique key to identify the object. */ func isExpiredObject(forKey key: Key) throws -> Bool + /** + Removes the object by the given key from cache in memory only. + - Parameter key: Unique key to identify the object. + */ + func removeInMemoryObject(forKey key: Key) throws } public extension StorageAware { diff --git a/Source/Shared/Storage/StorageObservationRegistry.swift b/Source/Shared/Storage/StorageObservationRegistry.swift index abd4927a..788631e6 100644 --- a/Source/Shared/Storage/StorageObservationRegistry.swift +++ b/Source/Shared/Storage/StorageObservationRegistry.swift @@ -28,11 +28,12 @@ public enum StorageChange: Equatable { case remove(key: Key) case removeAll case removeExpired + case removeInMemory(key: Key) } public func == (lhs: StorageChange, rhs: StorageChange) -> Bool { switch (lhs, rhs) { - case (.add(let key1), .add(let key2)), (.remove(let key1), .remove(let key2)): + case (.add(let key1), .add(let key2)), (.remove(let key1), .remove(let key2)), (.removeInMemory(let key1), .removeInMemory(let key2)): return key1 == key2 case (.removeAll, .removeAll), (.removeExpired, .removeExpired): return true diff --git a/Source/Shared/Storage/SyncStorage.swift b/Source/Shared/Storage/SyncStorage.swift index 51d15f0e..b7bab940 100644 --- a/Source/Shared/Storage/SyncStorage.swift +++ b/Source/Shared/Storage/SyncStorage.swift @@ -61,6 +61,13 @@ extension SyncStorage: StorageAware { try innerStorage.removeExpiredObjects() } } + + public func removeInMemoryObject(forKey key: Key) throws { + try serialQueue.sync { + try self.innerStorage.removeInMemoryObject(forKey: key) + } + } + } public extension SyncStorage { From ca92308ff98c60bccf7e9422896bf40d320f5799 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Thu, 4 Jan 2024 10:27:09 -0500 Subject: [PATCH 50/73] Update TransformerFactory.swift to add visionOS (#1) --- Source/Shared/Library/TransformerFactory.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shared/Library/TransformerFactory.swift b/Source/Shared/Library/TransformerFactory.swift index 00e4fe9a..8ee64ab9 100644 --- a/Source/Shared/Library/TransformerFactory.swift +++ b/Source/Shared/Library/TransformerFactory.swift @@ -9,7 +9,7 @@ public class TransformerFactory { return Transformer(toData: toData, fromData: fromData) } - #if os(iOS) || os(tvOS) || os(macOS) + #if os(iOS) || os(tvOS) || os(macOS) || os(visionOS) public static func forImage() -> Transformer { let toData: (Image) throws -> Data = { image in return try image.cache_toData().unwrapOrThrow(error: StorageError.transformerFail) From 8b895e5ee3522a3d2783108e3152a14548ea3035 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Thu, 4 Jan 2024 10:32:57 -0500 Subject: [PATCH 51/73] Update Types.swift to add visionOS --- Source/Shared/Library/Types.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shared/Library/Types.swift b/Source/Shared/Library/Types.swift index 81e7a301..e8408db4 100644 --- a/Source/Shared/Library/Types.swift +++ b/Source/Shared/Library/Types.swift @@ -1,4 +1,4 @@ -#if os(iOS) || os(tvOS) +#if os(iOS) || os(tvOS) || os(visionOS) import UIKit public typealias Image = UIImage #elseif os(watchOS) From 08608e367aa74a48e8f27ff44c6ba75a9f0f23aa Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Wed, 21 Feb 2024 11:06:47 +0900 Subject: [PATCH 52/73] add PrivacyInfo.xcprivacy --- Source/PrivacyInfo.xcprivacy | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Source/PrivacyInfo.xcprivacy diff --git a/Source/PrivacyInfo.xcprivacy b/Source/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/Source/PrivacyInfo.xcprivacy @@ -0,0 +1,5 @@ + + + + + From bf2fd30e560d69736fceb27b2da7ff728ba7e320 Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Wed, 21 Feb 2024 11:16:40 +0900 Subject: [PATCH 53/73] add resources --- Package.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index c167e646..30ce2b8d 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.1 +// swift-tools-version:5.5 import PackageDescription @@ -13,7 +13,8 @@ let package = Package( targets: [ .target( name: "Cache", - path: "Source" + path: "Source", + resources: [.copy("PrivacyInfo.xcprivacy")] ), .testTarget( name: "CacheTests", From e32a01da7a847266a0f7268ed467cd4b0fdf794e Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Wed, 21 Feb 2024 11:39:25 +0900 Subject: [PATCH 54/73] add NSPrivacyAccessedAPICategoryFileTimestamp for modificationDate and contentModificationDateKey --- Source/PrivacyInfo.xcprivacy | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Source/PrivacyInfo.xcprivacy b/Source/PrivacyInfo.xcprivacy index 0c67376e..1d40f906 100644 --- a/Source/PrivacyInfo.xcprivacy +++ b/Source/PrivacyInfo.xcprivacy @@ -1,5 +1,17 @@ - + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPITypeReasons + + C617.1 + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + + + From 049ef1af424ecb999c4ba8f8c172714fead2ce74 Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Wed, 21 Feb 2024 11:44:15 +0900 Subject: [PATCH 55/73] add NSPrivacyCollectedDataTypes --- Source/PrivacyInfo.xcprivacy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/PrivacyInfo.xcprivacy b/Source/PrivacyInfo.xcprivacy index 1d40f906..934f6eda 100644 --- a/Source/PrivacyInfo.xcprivacy +++ b/Source/PrivacyInfo.xcprivacy @@ -2,6 +2,8 @@ + NSPrivacyCollectedDataTypes + NSPrivacyAccessedAPITypes From 1014bad6967f8afcc2675e700e011894d8e93391 Mon Sep 17 00:00:00 2001 From: Greg Date: Fri, 22 Mar 2024 10:17:33 -0700 Subject: [PATCH 56/73] Include privacy manifest in podspec --- Cache.podspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cache.podspec b/Cache.podspec index c74a7c91..927952ad 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "7.0.0" + s.version = "7.0.1" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } @@ -16,6 +16,7 @@ Pod::Spec.new do |s| s.ios.source_files = 'Source/{iOS,Shared}/**/*' s.osx.source_files = 'Source/{Mac,Shared}/**/*' s.tvos.source_files = 'Source/{iOS,Shared}/**/*' + s.resources = 'Source/PrivacyInfo.xcprivacy' s.frameworks = 'Foundation' s.swift_version = '5.0' From ec9f3af90d63a8fb32cb2abe91d4c53f46d8dd93 Mon Sep 17 00:00:00 2001 From: Elvis <3lvis@users.noreply.github.com> Date: Tue, 26 Mar 2024 06:25:29 +0100 Subject: [PATCH 57/73] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 45afb49e..ee260ebf 100644 --- a/README.md +++ b/README.md @@ -398,10 +398,11 @@ If you want to load image into `UIImageView` or `NSImageView`, then we also have ### Cocoapods **Cache** is available through [CocoaPods](http://cocoapods.org). To install -it, simply add the following line to your Podfile: +it or update it, use the following line to your Podfile: ```ruby -pod 'Cache' +pod 'Cache', :git => 'https://github.com/hyperoslo/Cache.git' + ``` ### Carthage From 81fc4e5310db0bae64ea92f9f84551895b2a0e6f Mon Sep 17 00:00:00 2001 From: Elvis Date: Tue, 26 Mar 2024 10:30:54 +0100 Subject: [PATCH 58/73] Revert "Merge pull request #288 from escfrya/support-watchos" This reverts commit 472e8f59f9f4ca10a8b9b25342dc27db28d7caef, reversing changes made to ec9f3af90d63a8fb32cb2abe91d4c53f46d8dd93. --- Cache.podspec | 2 - Cache.xcodeproj/project.pbxproj | 208 ------------------ Source/Shared/Configuration/DiskConfig.swift | 2 +- Source/Shared/Library/ImageWrapper.swift | 2 +- .../Shared/Library/TransformerFactory.swift | 2 +- Source/Shared/Library/Types.swift | 2 +- Source/Shared/Storage/DiskStorage.swift | 2 +- Source/Shared/Storage/Storage+Transform.swift | 2 +- SupportFiles/watchOS/Info.plist | 22 -- 9 files changed, 6 insertions(+), 238 deletions(-) delete mode 100644 SupportFiles/watchOS/Info.plist diff --git a/Cache.podspec b/Cache.podspec index 5a6f4b02..927952ad 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -11,13 +11,11 @@ Pod::Spec.new do |s| s.ios.deployment_target = '11.0' s.osx.deployment_target = '10.12' s.tvos.deployment_target = '11.0' - s.watchos.deployment_target = '5.0' s.requires_arc = true s.ios.source_files = 'Source/{iOS,Shared}/**/*' s.osx.source_files = 'Source/{Mac,Shared}/**/*' s.tvos.source_files = 'Source/{iOS,Shared}/**/*' - s.watchos.source_files = 'Source/{iOS,Shared}/**/*' s.resources = 'Source/PrivacyInfo.xcprivacy' s.frameworks = 'Foundation' diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 16694beb..4b3d8b5b 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -153,40 +153,6 @@ D5A9D1C321144B65005DBD3F /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; D5A9D1C421144B65005DBD3F /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; D5A9D1C521144B65005DBD3F /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; - F812FB77264D57BC00D179F5 /* MemoryConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF984E1F694FFA00CE8F68 /* MemoryConfig.swift */; }; - F812FB78264D57BC00D179F5 /* DiskConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF984D1F694FFA00CE8F68 /* DiskConfig.swift */; }; - F812FB79264D57BC00D179F5 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98501F694FFA00CE8F68 /* Date+Extensions.swift */; }; - F812FB7A264D57BC00D179F5 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; - F812FB7B264D57BC00D179F5 /* JSONDecoder+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */; }; - F812FB7C264D57BC00D179F5 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */; }; - F812FB7D264D57BC00D179F5 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; - F812FB7E264D57C300D179F5 /* TransformerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27014A420D129EB003B45C7 /* TransformerFactory.swift */; }; - F812FB7F264D57C300D179F5 /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148B20D113EA003B45C7 /* Optional+Extension.swift */; }; - F812FB80264D57C300D179F5 /* JSONDictionaryWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */; }; - F812FB81264D57C300D179F5 /* ExpirationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98551F694FFA00CE8F68 /* ExpirationMode.swift */; }; - F812FB82264D57C300D179F5 /* ImageWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */; }; - F812FB83264D57C300D179F5 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98861F695B8F00CE8F68 /* Types.swift */; }; - F812FB84264D57C300D179F5 /* StorageError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98591F694FFA00CE8F68 /* StorageError.swift */; }; - F812FB85264D57C300D179F5 /* JSONArrayWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */; }; - F812FB86264D57C300D179F5 /* TypeWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148F20D1251E003B45C7 /* TypeWrapper.swift */; }; - F812FB87264D57C300D179F5 /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1B621134547005DBD3F /* ObservationToken.swift */; }; - F812FB88264D57C300D179F5 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5BF20D00DCC00BC940E /* Entry.swift */; }; - F812FB89264D57C300D179F5 /* MemoryCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270149320D125AC003B45C7 /* MemoryCapsule.swift */; }; - F812FB8A264D57C300D179F5 /* DataSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98531F694FFA00CE8F68 /* DataSerializer.swift */; }; - F812FB8B264D57C300D179F5 /* Expiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98561F694FFA00CE8F68 /* Expiry.swift */; }; - F812FB8C264D57C300D179F5 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC151FA3145000E4A2D5 /* MD5.swift */; }; - F812FB8D264D57C300D179F5 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270146F20D1018A003B45C7 /* Transformer.swift */; }; - F812FB8E264D57C800D179F5 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147F20D10982003B45C7 /* Storage.swift */; }; - F812FB8F264D57C800D179F5 /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; - F812FB90264D57C800D179F5 /* HybridStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147720D1046A003B45C7 /* HybridStorage.swift */; }; - F812FB91264D57C800D179F5 /* SyncStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147B20D107DA003B45C7 /* SyncStorage.swift */; }; - F812FB92264D57C800D179F5 /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5BB20D00D9300BC940E /* MemoryStorage.swift */; }; - F812FB93264D57C800D179F5 /* KeyObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51146522118337500197DCE /* KeyObservationRegistry.swift */; }; - F812FB94264D57C800D179F5 /* AsyncStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148320D10E76003B45C7 /* AsyncStorage.swift */; }; - F812FB95264D57C800D179F5 /* Storage+Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148720D11040003B45C7 /* Storage+Transform.swift */; }; - F812FB96264D57C800D179F5 /* DiskStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5C320D00DDB00BC940E /* DiskStorage.swift */; }; - F812FB97264D57C800D179F5 /* StorageAware.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147320D101F3003B45C7 /* StorageAware.swift */; }; - F812FB98264D57CC00D179F5 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A138C01EB29BFA00881A20 /* UIImage+Extensions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -283,9 +249,6 @@ D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageObservationRegistry.swift; sourceTree = ""; }; D5DC59E01C20593E003BD79B /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EBAACA991FBC369300FA206E /* SimpleStorage.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SimpleStorage.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; - F812FB6F264D579E00D179F5 /* Cache_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F812FB71264D579E00D179F5 /* Cache_watchOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Cache_watchOS.h; sourceTree = ""; }; - F812FB72264D579E00D179F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -334,13 +297,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F812FB6C264D579E00D179F5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -552,7 +508,6 @@ D5643E341C43F2CC00582E17 /* Playgrounds */, D5291C081C28220B00B702C9 /* Source */, D5DC59FA1C205AC9003BD79B /* Tests */, - F812FB70264D579E00D179F5 /* Cache-watchOS */, D5DC59E11C20593E003BD79B /* Products */, ); indentWidth = 4; @@ -568,7 +523,6 @@ D5291D691C283B5400B702C9 /* Cache-Mac-Tests.xctest */, BDEDD3561DBCE5B1007416A6 /* Cache.framework */, BDEDD3781DBCEB8A007416A6 /* Cache-tvOS-Tests.xctest */, - F812FB6F264D579E00D179F5 /* Cache_watchOS.framework */, ); name = Products; sourceTree = ""; @@ -583,15 +537,6 @@ path = Tests; sourceTree = ""; }; - F812FB70264D579E00D179F5 /* Cache-watchOS */ = { - isa = PBXGroup; - children = ( - F812FB71264D579E00D179F5 /* Cache_watchOS.h */, - F812FB72264D579E00D179F5 /* Info.plist */, - ); - path = "Cache-watchOS"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -616,13 +561,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F812FB6A264D579E00D179F5 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -734,24 +672,6 @@ productReference = D5DC59E01C20593E003BD79B /* Cache.framework */; productType = "com.apple.product-type.framework"; }; - F812FB6E264D579E00D179F5 /* Cache-watchOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = F812FB76264D579E00D179F5 /* Build configuration list for PBXNativeTarget "Cache-watchOS" */; - buildPhases = ( - F812FB6A264D579E00D179F5 /* Headers */, - F812FB6B264D579E00D179F5 /* Sources */, - F812FB6C264D579E00D179F5 /* Frameworks */, - F812FB6D264D579E00D179F5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Cache-watchOS"; - productName = "Cache-watchOS"; - productReference = F812FB6F264D579E00D179F5 /* Cache_watchOS.framework */; - productType = "com.apple.product-type.framework"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -785,10 +705,6 @@ CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; - F812FB6E264D579E00D179F5 = { - CreatedOnToolsVersion = 12.5; - ProvisioningStyle = Manual; - }; }; }; buildConfigurationList = D5DC59DA1C20593E003BD79B /* Build configuration list for PBXProject "Cache" */; @@ -810,7 +726,6 @@ D5291D681C283B5400B702C9 /* Cache-Mac-Tests */, BDEDD3551DBCE5B1007416A6 /* Cache-tvOS */, BDEDD3771DBCEB8A007416A6 /* Cache-tvOS-Tests */, - F812FB6E264D579E00D179F5 /* Cache-watchOS */, ); }; /* End PBXProject section */ @@ -858,13 +773,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F812FB6D264D579E00D179F5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1053,47 +961,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F812FB6B264D579E00D179F5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - F812FB95264D57C800D179F5 /* Storage+Transform.swift in Sources */, - F812FB81264D57C300D179F5 /* ExpirationMode.swift in Sources */, - F812FB82264D57C300D179F5 /* ImageWrapper.swift in Sources */, - F812FB78264D57BC00D179F5 /* DiskConfig.swift in Sources */, - F812FB8A264D57C300D179F5 /* DataSerializer.swift in Sources */, - F812FB8D264D57C300D179F5 /* Transformer.swift in Sources */, - F812FB8E264D57C800D179F5 /* Storage.swift in Sources */, - F812FB7D264D57BC00D179F5 /* FileManager+Extensions.swift in Sources */, - F812FB8B264D57C300D179F5 /* Expiry.swift in Sources */, - F812FB92264D57C800D179F5 /* MemoryStorage.swift in Sources */, - F812FB7C264D57BC00D179F5 /* URL+Extensions.swift in Sources */, - F812FB80264D57C300D179F5 /* JSONDictionaryWrapper.swift in Sources */, - F812FB96264D57C800D179F5 /* DiskStorage.swift in Sources */, - F812FB88264D57C300D179F5 /* Entry.swift in Sources */, - F812FB89264D57C300D179F5 /* MemoryCapsule.swift in Sources */, - F812FB8C264D57C300D179F5 /* MD5.swift in Sources */, - F812FB7B264D57BC00D179F5 /* JSONDecoder+Extensions.swift in Sources */, - F812FB91264D57C800D179F5 /* SyncStorage.swift in Sources */, - F812FB87264D57C300D179F5 /* ObservationToken.swift in Sources */, - F812FB97264D57C800D179F5 /* StorageAware.swift in Sources */, - F812FB85264D57C300D179F5 /* JSONArrayWrapper.swift in Sources */, - F812FB7F264D57C300D179F5 /* Optional+Extension.swift in Sources */, - F812FB8F264D57C800D179F5 /* StorageObservationRegistry.swift in Sources */, - F812FB83264D57C300D179F5 /* Types.swift in Sources */, - F812FB90264D57C800D179F5 /* HybridStorage.swift in Sources */, - F812FB77264D57BC00D179F5 /* MemoryConfig.swift in Sources */, - F812FB93264D57C800D179F5 /* KeyObservationRegistry.swift in Sources */, - F812FB84264D57C300D179F5 /* StorageError.swift in Sources */, - F812FB7A264D57BC00D179F5 /* Hasher+constantAccrossExecutions.swift in Sources */, - F812FB94264D57C800D179F5 /* AsyncStorage.swift in Sources */, - F812FB7E264D57C300D179F5 /* TransformerFactory.swift in Sources */, - F812FB98264D57CC00D179F5 /* UIImage+Extensions.swift in Sources */, - F812FB79264D57BC00D179F5 /* Date+Extensions.swift in Sources */, - F812FB86264D57C300D179F5 /* TypeWrapper.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -1463,72 +1330,6 @@ }; name = Release; }; - F812FB74264D579E00D179F5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Manual; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/watchOS/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-watchOS"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = watchos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 5.0; - }; - name = Debug; - }; - F812FB75264D579E00D179F5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Manual; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/watchOS/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-watchOS"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = watchos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 5.0; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1595,15 +1396,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - F812FB76264D579E00D179F5 /* Build configuration list for PBXNativeTarget "Cache-watchOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - F812FB74264D579E00D179F5 /* Debug */, - F812FB75264D579E00D179F5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = D5DC59D71C20593E003BD79B /* Project object */; diff --git a/Source/Shared/Configuration/DiskConfig.swift b/Source/Shared/Configuration/DiskConfig.swift index e57212a3..3d0a01c5 100644 --- a/Source/Shared/Configuration/DiskConfig.swift +++ b/Source/Shared/Configuration/DiskConfig.swift @@ -10,7 +10,7 @@ public struct DiskConfig { public let maxSize: UInt /// A folder to store the disk cache contents. Defaults to a prefixed directory in Caches if nil public let directory: URL? - #if os(iOS) || os(tvOS) || os(watchOS) + #if os(iOS) || os(tvOS) /// Data protection is used to store files in an encrypted format on disk and to decrypt them on demand. /// Support only on iOS and tvOS. public let protectionType: FileProtectionType? diff --git a/Source/Shared/Library/ImageWrapper.swift b/Source/Shared/Library/ImageWrapper.swift index 5bc0cdde..cc9fd7d7 100644 --- a/Source/Shared/Library/ImageWrapper.swift +++ b/Source/Shared/Library/ImageWrapper.swift @@ -1,6 +1,6 @@ import Foundation -#if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) +#if os(iOS) || os(tvOS) || os(macOS) public struct ImageWrapper: Codable { public let image: Image diff --git a/Source/Shared/Library/TransformerFactory.swift b/Source/Shared/Library/TransformerFactory.swift index 05fd6b4b..8ee64ab9 100644 --- a/Source/Shared/Library/TransformerFactory.swift +++ b/Source/Shared/Library/TransformerFactory.swift @@ -9,7 +9,7 @@ public class TransformerFactory { return Transformer(toData: toData, fromData: fromData) } - #if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) || os(visionOS) + #if os(iOS) || os(tvOS) || os(macOS) || os(visionOS) public static func forImage() -> Transformer { let toData: (Image) throws -> Data = { image in return try image.cache_toData().unwrapOrThrow(error: StorageError.transformerFail) diff --git a/Source/Shared/Library/Types.swift b/Source/Shared/Library/Types.swift index 52c03b22..e8408db4 100644 --- a/Source/Shared/Library/Types.swift +++ b/Source/Shared/Library/Types.swift @@ -1,4 +1,4 @@ -#if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) +#if os(iOS) || os(tvOS) || os(visionOS) import UIKit public typealias Image = UIImage #elseif os(watchOS) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index d21a31f2..b0bf9e37 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -40,7 +40,7 @@ final public class DiskStorage { try createDirectory() // protection - #if os(iOS) || os(tvOS) || os(watchOS) + #if os(iOS) || os(tvOS) if let protectionType = config.protectionType { try setDirectoryAttributes([ FileAttributeKey.protectionKey: protectionType diff --git a/Source/Shared/Storage/Storage+Transform.swift b/Source/Shared/Storage/Storage+Transform.swift index af1bc366..494e6afb 100644 --- a/Source/Shared/Storage/Storage+Transform.swift +++ b/Source/Shared/Storage/Storage+Transform.swift @@ -7,7 +7,7 @@ public extension Storage { } - #if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) + #if os(iOS) || os(tvOS) || os(macOS) func transformImage() -> Storage { let storage = transform(transformer: TransformerFactory.forImage()) return storage diff --git a/SupportFiles/watchOS/Info.plist b/SupportFiles/watchOS/Info.plist deleted file mode 100644 index 37f13eb0..00000000 --- a/SupportFiles/watchOS/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - - From f377c321d5a5a0f11327ca04896030172fc2fbd1 Mon Sep 17 00:00:00 2001 From: Elvis Date: Tue, 26 Mar 2024 11:10:49 +0100 Subject: [PATCH 59/73] Clean up and add watchOS support --- Cache.podspec | 7 +- Cache.xcodeproj/project.pbxproj | 347 ++++++++++++++++-- .../xcshareddata/xcschemes/Cache-iOS.xcscheme | 2 +- .../xcschemes/Cache-macOS.xcscheme | 2 +- .../xcschemes/Cache-tvOS.xcscheme | 2 +- Source/Shared/Configuration/DiskConfig.swift | 11 - Source/Shared/Library/ImageWrapper.swift | 6 +- .../Shared/Library/TransformerFactory.swift | 6 +- Source/Shared/Library/Types.swift | 3 +- Source/Shared/Storage/DiskStorage.swift | 3 - Source/Shared/Storage/Storage+Transform.swift | 6 +- Tests/Shared/TestHelper.swift | 6 +- Tests/iOS/Helpers/TestHelper+iOS.swift | 2 +- .../iOS/Helpers/UIImage+ExtensionsTests.swift | 2 +- 14 files changed, 347 insertions(+), 58 deletions(-) diff --git a/Cache.podspec b/Cache.podspec index 927952ad..29f1b3c1 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -8,9 +8,10 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/hyperoslo/Cache.git", :tag => s.version.to_s } s.social_media_url = 'https://twitter.com/hyperoslo' - s.ios.deployment_target = '11.0' - s.osx.deployment_target = '10.12' - s.tvos.deployment_target = '11.0' + s.ios.deployment_target = '12.0' + s.osx.deployment_target = '10.14' + s.tvos.deployment_target = '12.0' + s.watchos.deployment_target = '6.0' s.requires_arc = true s.ios.source_files = 'Source/{iOS,Shared}/**/*' diff --git a/Cache.xcodeproj/project.pbxproj b/Cache.xcodeproj/project.pbxproj index 4b3d8b5b..ac78aacf 100644 --- a/Cache.xcodeproj/project.pbxproj +++ b/Cache.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -17,6 +17,40 @@ 2292AB85252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; 2292AB86252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; 2292AB87252A14F50031F3B9 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; + 285DC4822BB2D1440036F206 /* DiskConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF984D1F694FFA00CE8F68 /* DiskConfig.swift */; }; + 285DC4832BB2D1440036F206 /* MemoryConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF984E1F694FFA00CE8F68 /* MemoryConfig.swift */; }; + 285DC4842BB2D1440036F206 /* Hasher+constantAccrossExecutions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E791649250E2AA500A71666 /* Hasher+constantAccrossExecutions.swift */; }; + 285DC4852BB2D1440036F206 /* JSONDecoder+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28897041F8B79B300C61DEE /* JSONDecoder+Extensions.swift */; }; + 285DC4862BB2D1440036F206 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98501F694FFA00CE8F68 /* Date+Extensions.swift */; }; + 285DC4872BB2D1440036F206 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */; }; + 285DC4882BB2D1440036F206 /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */; }; + 285DC4892BB2D1440036F206 /* DataSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98531F694FFA00CE8F68 /* DataSerializer.swift */; }; + 285DC48A2BB2D1440036F206 /* ExpirationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98551F694FFA00CE8F68 /* ExpirationMode.swift */; }; + 285DC48B2BB2D1440036F206 /* Expiry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98561F694FFA00CE8F68 /* Expiry.swift */; }; + 285DC48C2BB2D1440036F206 /* ImageWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98571F694FFA00CE8F68 /* ImageWrapper.swift */; }; + 285DC48D2BB2D1440036F206 /* StorageError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98591F694FFA00CE8F68 /* StorageError.swift */; }; + 285DC48E2BB2D1440036F206 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98861F695B8F00CE8F68 /* Types.swift */; }; + 285DC48F2BB2D1440036F206 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC151FA3145000E4A2D5 /* MD5.swift */; }; + 285DC4902BB2D1440036F206 /* JSONDictionaryWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC1F1FA3411300E4A2D5 /* JSONDictionaryWrapper.swift */; }; + 285DC4912BB2D1440036F206 /* JSONArrayWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D4CC231FA3426B00E4A2D5 /* JSONArrayWrapper.swift */; }; + 285DC4922BB2D1440036F206 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5BF20D00DCC00BC940E /* Entry.swift */; }; + 285DC4932BB2D1440036F206 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270146F20D1018A003B45C7 /* Transformer.swift */; }; + 285DC4942BB2D1440036F206 /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148B20D113EA003B45C7 /* Optional+Extension.swift */; }; + 285DC4952BB2D1440036F206 /* TypeWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148F20D1251E003B45C7 /* TypeWrapper.swift */; }; + 285DC4962BB2D1440036F206 /* MemoryCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270149320D125AC003B45C7 /* MemoryCapsule.swift */; }; + 285DC4972BB2D1440036F206 /* TransformerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27014A420D129EB003B45C7 /* TransformerFactory.swift */; }; + 285DC4982BB2D1440036F206 /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1B621134547005DBD3F /* ObservationToken.swift */; }; + 285DC4992BB2D1440036F206 /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5BB20D00D9300BC940E /* MemoryStorage.swift */; }; + 285DC49A2BB2D1440036F206 /* DiskStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D221E5C320D00DDB00BC940E /* DiskStorage.swift */; }; + 285DC49B2BB2D1440036F206 /* StorageAware.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147320D101F3003B45C7 /* StorageAware.swift */; }; + 285DC49C2BB2D1440036F206 /* HybridStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147720D1046A003B45C7 /* HybridStorage.swift */; }; + 285DC49D2BB2D1440036F206 /* SyncStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147B20D107DA003B45C7 /* SyncStorage.swift */; }; + 285DC49E2BB2D1440036F206 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270147F20D10982003B45C7 /* Storage.swift */; }; + 285DC49F2BB2D1440036F206 /* AsyncStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148320D10E76003B45C7 /* AsyncStorage.swift */; }; + 285DC4A02BB2D1440036F206 /* Storage+Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270148720D11040003B45C7 /* Storage+Transform.swift */; }; + 285DC4A12BB2D1440036F206 /* StorageObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9D1C221144B65005DBD3F /* StorageObservationRegistry.swift */; }; + 285DC4A22BB2D1440036F206 /* KeyObservationRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51146522118337500197DCE /* KeyObservationRegistry.swift */; }; + 285DC4A32BB2D2DB0036F206 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A138C01EB29BFA00881A20 /* UIImage+Extensions.swift */; }; BDEDD37D1DBCEB8A007416A6 /* Cache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDEDD3561DBCE5B1007416A6 /* Cache.framework */; }; D21B667C1F6A723C00125DE1 /* DataSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98531F694FFA00CE8F68 /* DataSerializer.swift */; }; D21B667E1F6A723C00125DE1 /* ExpirationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CF98551F694FFA00CE8F68 /* ExpirationMode.swift */; }; @@ -184,6 +218,7 @@ 0E79164D250E2B0400A71666 /* Hasher+constantAccrossExecutions+Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Hasher+constantAccrossExecutions+Tests.swift"; sourceTree = ""; }; 2292AB7A252A14520031F3B9 /* URL+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = ""; }; 2292AB84252A14F50031F3B9 /* FileManager+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Extensions.swift"; sourceTree = ""; }; + 285DC47A2BB2CFCC0036F206 /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BDEDD3561DBCE5B1007416A6 /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BDEDD3781DBCEB8A007416A6 /* Cache-tvOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Cache-tvOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; D221E5BB20D00D9300BC940E /* MemoryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryStorage.swift; sourceTree = ""; }; @@ -252,6 +287,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 285DC4772BB2CFCC0036F206 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; BDEDD3521DBCE5B1007416A6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -523,6 +565,7 @@ D5291D691C283B5400B702C9 /* Cache-Mac-Tests.xctest */, BDEDD3561DBCE5B1007416A6 /* Cache.framework */, BDEDD3781DBCEB8A007416A6 /* Cache-tvOS-Tests.xctest */, + 285DC47A2BB2CFCC0036F206 /* Cache.framework */, ); name = Products; sourceTree = ""; @@ -540,6 +583,13 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 285DC4812BB2D11B0036F206 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; BDEDD3531DBCE5B1007416A6 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -564,6 +614,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 285DC4792BB2CFCC0036F206 /* Cache-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 285DC47E2BB2CFCC0036F206 /* Build configuration list for PBXNativeTarget "Cache-watchOS" */; + buildPhases = ( + 285DC4812BB2D11B0036F206 /* Headers */, + 285DC4762BB2CFCC0036F206 /* Sources */, + 285DC4772BB2CFCC0036F206 /* Frameworks */, + 285DC4782BB2CFCC0036F206 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Cache-watchOS"; + productName = "Cache-watchOS"; + productReference = 285DC47A2BB2CFCC0036F206 /* Cache.framework */; + productType = "com.apple.product-type.framework"; + }; BDEDD3551DBCE5B1007416A6 /* Cache-tvOS */ = { isa = PBXNativeTarget; buildConfigurationList = BDEDD35D1DBCE5B1007416A6 /* Build configuration list for PBXNativeTarget "Cache-tvOS" */; @@ -678,10 +746,14 @@ D5DC59D71C20593E003BD79B /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1530; ORGANIZATIONNAME = "Hyper Interaktiv AS"; TargetAttributes = { + 285DC4792BB2CFCC0036F206 = { + CreatedOnToolsVersion = 15.3; + }; BDEDD3551DBCE5B1007416A6 = { CreatedOnToolsVersion = 8.0; ProvisioningStyle = Manual; @@ -726,11 +798,19 @@ D5291D681C283B5400B702C9 /* Cache-Mac-Tests */, BDEDD3551DBCE5B1007416A6 /* Cache-tvOS */, BDEDD3771DBCEB8A007416A6 /* Cache-tvOS-Tests */, + 285DC4792BB2CFCC0036F206 /* Cache-watchOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 285DC4782BB2CFCC0036F206 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; BDEDD3541DBCE5B1007416A6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -776,6 +856,47 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 285DC4762BB2CFCC0036F206 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 285DC4A32BB2D2DB0036F206 /* UIImage+Extensions.swift in Sources */, + 285DC4822BB2D1440036F206 /* DiskConfig.swift in Sources */, + 285DC4832BB2D1440036F206 /* MemoryConfig.swift in Sources */, + 285DC4842BB2D1440036F206 /* Hasher+constantAccrossExecutions.swift in Sources */, + 285DC4852BB2D1440036F206 /* JSONDecoder+Extensions.swift in Sources */, + 285DC4862BB2D1440036F206 /* Date+Extensions.swift in Sources */, + 285DC4872BB2D1440036F206 /* URL+Extensions.swift in Sources */, + 285DC4882BB2D1440036F206 /* FileManager+Extensions.swift in Sources */, + 285DC4892BB2D1440036F206 /* DataSerializer.swift in Sources */, + 285DC48A2BB2D1440036F206 /* ExpirationMode.swift in Sources */, + 285DC48B2BB2D1440036F206 /* Expiry.swift in Sources */, + 285DC48C2BB2D1440036F206 /* ImageWrapper.swift in Sources */, + 285DC48D2BB2D1440036F206 /* StorageError.swift in Sources */, + 285DC48E2BB2D1440036F206 /* Types.swift in Sources */, + 285DC48F2BB2D1440036F206 /* MD5.swift in Sources */, + 285DC4902BB2D1440036F206 /* JSONDictionaryWrapper.swift in Sources */, + 285DC4912BB2D1440036F206 /* JSONArrayWrapper.swift in Sources */, + 285DC4922BB2D1440036F206 /* Entry.swift in Sources */, + 285DC4932BB2D1440036F206 /* Transformer.swift in Sources */, + 285DC4942BB2D1440036F206 /* Optional+Extension.swift in Sources */, + 285DC4952BB2D1440036F206 /* TypeWrapper.swift in Sources */, + 285DC4962BB2D1440036F206 /* MemoryCapsule.swift in Sources */, + 285DC4972BB2D1440036F206 /* TransformerFactory.swift in Sources */, + 285DC4982BB2D1440036F206 /* ObservationToken.swift in Sources */, + 285DC4992BB2D1440036F206 /* MemoryStorage.swift in Sources */, + 285DC49A2BB2D1440036F206 /* DiskStorage.swift in Sources */, + 285DC49B2BB2D1440036F206 /* StorageAware.swift in Sources */, + 285DC49C2BB2D1440036F206 /* HybridStorage.swift in Sources */, + 285DC49D2BB2D1440036F206 /* SyncStorage.swift in Sources */, + 285DC49E2BB2D1440036F206 /* Storage.swift in Sources */, + 285DC49F2BB2D1440036F206 /* AsyncStorage.swift in Sources */, + 285DC4A02BB2D1440036F206 /* Storage+Transform.swift in Sources */, + 285DC4A12BB2D1440036F206 /* StorageObservationRegistry.swift in Sources */, + 285DC4A22BB2D1440036F206 /* KeyObservationRegistry.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; BDEDD3511DBCE5B1007416A6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -982,6 +1103,100 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 285DC47F2BB2CFCC0036F206 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Hyper Interaktiv AS. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-watchOS"; + PRODUCT_NAME = Cache; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 6.0; + }; + name = Debug; + }; + 285DC4802BB2CFCC0036F206 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Hyper Interaktiv AS. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-watchOS"; + PRODUCT_NAME = Cache; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 6.0; + }; + name = Release; + }; BDEDD35B1DBCE5B1007416A6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -994,17 +1209,23 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS"; PRODUCT_NAME = Cache; SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Debug; }; @@ -1020,16 +1241,22 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS"; PRODUCT_NAME = Cache; SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Release; }; @@ -1043,7 +1270,11 @@ DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/tvOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; @@ -1064,7 +1295,11 @@ DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/tvOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; @@ -1079,10 +1314,17 @@ CLANG_ENABLE_MODULES = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/iOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator watchos watchsimulator"; + SUPPORTS_MACCATALYST = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2,4"; }; name = Debug; }; @@ -1092,9 +1334,16 @@ CLANG_ENABLE_MODULES = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/iOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator watchos watchsimulator"; + SUPPORTS_MACCATALYST = YES; + TARGETED_DEVICE_FAMILY = "1,2,4"; }; name = Release; }; @@ -1103,16 +1352,23 @@ buildSettings = { CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.12; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-Mac"; PRODUCT_NAME = Cache; SDKROOT = macosx; @@ -1125,16 +1381,23 @@ buildSettings = { CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.12; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-Mac"; PRODUCT_NAME = Cache; SDKROOT = macosx; @@ -1147,9 +1410,14 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/Mac/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-MacTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1162,9 +1430,14 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/Tests/Mac/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Cache-MacTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1221,7 +1494,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -1276,10 +1549,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -1291,19 +1565,26 @@ D5DC59F51C20593E003BD79B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_IDENTITY = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -1312,19 +1593,26 @@ D5DC59F61C20593E003BD79B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_IDENTITY = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Cache; PRODUCT_NAME = Cache; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -1333,6 +1621,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 285DC47E2BB2CFCC0036F206 /* Build configuration list for PBXNativeTarget "Cache-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 285DC47F2BB2CFCC0036F206 /* Debug */, + 285DC4802BB2CFCC0036F206 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; BDEDD35D1DBCE5B1007416A6 /* Build configuration list for PBXNativeTarget "Cache-tvOS" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme index fc762f31..2938ef18 100644 --- a/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme +++ b/Cache.xcodeproj/xcshareddata/xcschemes/Cache-iOS.xcscheme @@ -1,6 +1,6 @@ (toData: toData, fromData: fromData) } - #if os(iOS) || os(tvOS) || os(macOS) || os(visionOS) public static func forImage() -> Transformer { let toData: (Image) throws -> Data = { image in return try image.cache_toData().unwrapOrThrow(error: StorageError.transformerFail) @@ -21,7 +24,6 @@ public class TransformerFactory { return Transformer(toData: toData, fromData: fromData) } - #endif public static func forCodable(ofType: U.Type) -> Transformer { let toData: (U) throws -> Data = { object in diff --git a/Source/Shared/Library/Types.swift b/Source/Shared/Library/Types.swift index e8408db4..44d6265c 100644 --- a/Source/Shared/Library/Types.swift +++ b/Source/Shared/Library/Types.swift @@ -1,7 +1,6 @@ -#if os(iOS) || os(tvOS) || os(visionOS) +#if canImport(UIKit) import UIKit public typealias Image = UIImage -#elseif os(watchOS) #elseif os(OSX) import AppKit diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index b0bf9e37..78d9b733 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -39,14 +39,11 @@ final public class DiskStorage { try createDirectory() - // protection - #if os(iOS) || os(tvOS) if let protectionType = config.protectionType { try setDirectoryAttributes([ FileAttributeKey.protectionKey: protectionType ]) } - #endif } public required init(config: DiskConfig, fileManager: FileManager = FileManager.default, path: String, transformer: Transformer) { diff --git a/Source/Shared/Storage/Storage+Transform.swift b/Source/Shared/Storage/Storage+Transform.swift index 494e6afb..d043a5d3 100644 --- a/Source/Shared/Storage/Storage+Transform.swift +++ b/Source/Shared/Storage/Storage+Transform.swift @@ -1,3 +1,7 @@ +#if canImport(UIKit) +import UIKit +#endif + import Foundation public extension Storage { @@ -7,12 +11,10 @@ public extension Storage { } - #if os(iOS) || os(tvOS) || os(macOS) func transformImage() -> Storage { let storage = transform(transformer: TransformerFactory.forImage()) return storage } - #endif func transformCodable(ofType: U.Type) -> Storage { let storage = transform(transformer: TransformerFactory.forCodable(ofType: U.self)) diff --git a/Tests/Shared/TestHelper.swift b/Tests/Shared/TestHelper.swift index 07b42d25..9c34eab7 100644 --- a/Tests/Shared/TestHelper.swift +++ b/Tests/Shared/TestHelper.swift @@ -1,8 +1,8 @@ import Foundation -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit -#elseif os(OSX) +#elseif os(macOS) import AppKit #endif @@ -13,7 +13,7 @@ struct TestHelper { } static func triggerApplicationEvents() { - #if os(iOS) || os(tvOS) + #if os(iOS) || os(tvOS) || os(visionOS) NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.post(name: UIApplication.willTerminateNotification, object: nil) #elseif os(macOS) diff --git a/Tests/iOS/Helpers/TestHelper+iOS.swift b/Tests/iOS/Helpers/TestHelper+iOS.swift index ab840d04..9bb32afe 100644 --- a/Tests/iOS/Helpers/TestHelper+iOS.swift +++ b/Tests/iOS/Helpers/TestHelper+iOS.swift @@ -1,4 +1,4 @@ -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit extension TestHelper { diff --git a/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift b/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift index 307a0578..97e2be7e 100644 --- a/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift +++ b/Tests/iOS/Helpers/UIImage+ExtensionsTests.swift @@ -1,4 +1,4 @@ -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit extension UIImage { From f44a8f6b5ec27730198725ccc542fef0d1cc6b3d Mon Sep 17 00:00:00 2001 From: Elvis <3lvis@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:26:39 +0100 Subject: [PATCH 60/73] Update Cache.podspec --- Cache.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cache.podspec b/Cache.podspec index 29f1b3c1..4698519b 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "7.0.1" + s.version = "7.1.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } From 3fdb0aa24a4ba189564507764245adad36dc105a Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Sun, 26 May 2024 16:14:14 +0900 Subject: [PATCH 61/73] add async await --- Source/Shared/Storage/AsyncStorage.swift | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/Source/Shared/Storage/AsyncStorage.swift b/Source/Shared/Storage/AsyncStorage.swift index 4f1c1b04..42becd76 100644 --- a/Source/Shared/Storage/AsyncStorage.swift +++ b/Source/Shared/Storage/AsyncStorage.swift @@ -138,3 +138,65 @@ public extension AsyncStorage { return storage } } + +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +public extension AsyncStorage { + func entry(forKey key: Key) async throws -> Entry { + try await withCheckedThrowingContinuation { continuation in + entry(forKey: key) { + continuation.resume(with: $0) + } + } + } + + func removeObject(forKey key: Key) async throws { + try await withCheckedThrowingContinuation { continuation in + removeObject(forKey: key) { + continuation.resume(with: $0) + } + } + } + + func setObject( + _ object: Value, + forKey key: Key, + expiry: Expiry? = nil) async throws { + try await withCheckedThrowingContinuation { continuation in + setObject(object, forKey: key, expiry: expiry) { + continuation.resume(with: $0) + } + } + } + + func removeAll() async throws { + try await withCheckedThrowingContinuation { continuation in + removeAll { + continuation.resume(with: $0) + } + } + } + + func removeExpiredObjects() async throws { + try await withCheckedThrowingContinuation { continuation in + removeExpiredObjects { + continuation.resume(with: $0) + } + } + } + + func object(forKey key: Key) async throws -> Value { + try await withCheckedThrowingContinuation { continuation in + object(forKey: key) { + continuation.resume(with: $0) + } + } + } + + func objectExists(forKey key: Key) async throws -> Bool { + try await withCheckedThrowingContinuation { continuation in + objectExists(forKey: key) { + continuation.resume(with: $0) + } + } + } +} From 91ac56f4cd4a7dbb6490d41989636a960a8d165c Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Sun, 26 May 2024 16:41:08 +0900 Subject: [PATCH 62/73] add tests --- Tests/Shared/TestCase+Extensions.swift | 12 +++++++++ .../iOS/Tests/Storage/AsyncStorageTests.swift | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Tests/Shared/TestCase+Extensions.swift b/Tests/Shared/TestCase+Extensions.swift index c3ba232e..8174187b 100644 --- a/Tests/Shared/TestCase+Extensions.swift +++ b/Tests/Shared/TestCase+Extensions.swift @@ -5,11 +5,23 @@ extension XCTestCase { try closure() } + func given(_ description: String, closure: () async throws -> Void) async rethrows { + try await closure() + } + func when(_ description: String, closure: () throws -> Void) rethrows { try closure() } + func when(_ description: String, closure: () async throws -> Void) async rethrows { + try await closure() + } + func then(_ description: String, closure: () throws -> Void) rethrows { try closure() } + + func then(_ description: String, closure: () async throws -> Void) async rethrows { + try await closure() + } } diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index 1251d152..eb268d20 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -36,6 +36,13 @@ final class AsyncStorageTests: XCTestCase { wait(for: [expectation], timeout: 1) } + func testSetObject() async throws { + try await storage.setObject(user, forKey: "user") + let cachedUser = try await storage.object(forKey: "user") + + XCTAssertEqual(cachedUser, self.user) + } + func testRemoveAll() { let intStorage = storage.transform(transformer: TransformerFactory.forCodable(ofType: Int.self)) let expectation = self.expectation(description: #function) @@ -62,4 +69,24 @@ final class AsyncStorageTests: XCTestCase { wait(for: [expectation], timeout: 1) } + + func testRemoveAll() async throws { + let intStorage = storage.transform(transformer: TransformerFactory.forCodable(ofType: Int.self)) + try await given("add a lot of objects") { + for i in 0 ..< 100 { + try await intStorage.setObject(i, forKey: "key-\(i)") + } + } + + try await when("remove all") { + try await intStorage.removeAll() + } + + await then("all are removed") { + do { + _ = try await intStorage.objectExists(forKey: "key-99") + XCTFail() + } catch {} + } + } } From 62374db4d1916e808f81a22cec7eeb964f501d9b Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Sun, 26 May 2024 16:50:57 +0900 Subject: [PATCH 63/73] add example for async await into readme --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index ee260ebf..cb6805db 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,45 @@ storage.async.removeExpiredObjects() { result in } ``` +#### Swift Concurrency + +```swift +do { + try await storage.async.setObject("Oslo", forKey: "my favorite city") + print("saved successfully") +} catch { + print(error) +} + +do { + let city = try await storage.async.object(forKey: "my favorite city") + print("my favorite city is \(city)") +} catch { + print(error) +} + +do { + let exists = try await storage.async.objectExists(forKey: "my favorite city") + if exists { + print("I have a favorite city") + } +} catch {} + +do { + try await storage.async.remoeAll() + print("removal completes") +} catch { + print(error) +} + +do { + try await storage.async.removeExpiredObjects() + print("removal completes") +} catch { + print(error) +} +``` + ### Expiry date By default, all saved objects have the same expiry as the expiry you specify in `DiskConfig` or `MemoryConfig`. You can overwrite this for a specific object by specifying `expiry` for `setObject` From 4740e2ef873ff3e1f3a117c7084002daf29f3178 Mon Sep 17 00:00:00 2001 From: Keita Watanabe Date: Sun, 26 May 2024 16:58:40 +0900 Subject: [PATCH 64/73] fix readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ee260ebf..3cb9968b 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ let score = try? storage.object(forKey: "score") let favoriteCharacter = try? storage.object(forKey: "my favorite city") // Check if an object exists -let hasFavoriteCharacter = try? storage.existsObject(forKey: "my favorite city") +let hasFavoriteCharacter = try? storage.objectExists(forKey: "my favorite city") // Remove an object in storage try? storage.removeObject(forKey: "my favorite city") @@ -263,7 +263,7 @@ storage.async.object(forKey: "my favorite city") { result in } } -storage.async.existsObject(forKey: "my favorite city") { result in +storage.async.objectExists(forKey: "my favorite city") { result in if case .success(let exists) = result, exists { print("I have a favorite city") } @@ -299,7 +299,7 @@ try? storage.setObject("This is a string", forKey: "string") // A given expiry date will be applied to the item try? storage.setObject( "This is a string", - forKey: "string" + forKey: "string", expiry: .date(Date().addingTimeInterval(2 * 3600)) ) From fd97438a85d44aa4f7186145cdba90e3c36f1c94 Mon Sep 17 00:00:00 2001 From: Elvis Date: Sun, 26 May 2024 23:01:33 +0200 Subject: [PATCH 65/73] Fix tests --- Tests/iOS/Tests/Storage/AsyncStorageTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift index eb268d20..fb5023e7 100644 --- a/Tests/iOS/Tests/Storage/AsyncStorageTests.swift +++ b/Tests/iOS/Tests/Storage/AsyncStorageTests.swift @@ -36,6 +36,7 @@ final class AsyncStorageTests: XCTestCase { wait(for: [expectation], timeout: 1) } +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func testSetObject() async throws { try await storage.setObject(user, forKey: "user") let cachedUser = try await storage.object(forKey: "user") @@ -70,6 +71,7 @@ final class AsyncStorageTests: XCTestCase { wait(for: [expectation], timeout: 1) } +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func testRemoveAll() async throws { let intStorage = storage.transform(transformer: TransformerFactory.forCodable(ofType: Int.self)) try await given("add a lot of objects") { From f7805bacdb5d9ebd81212f1fb4b9a75995aca148 Mon Sep 17 00:00:00 2001 From: Lucas Romano Date: Tue, 18 Jun 2024 18:57:24 -0300 Subject: [PATCH 66/73] Fix xcprivacy on podscpec Fix xcprivacy on podspec --- Cache.podspec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cache.podspec b/Cache.podspec index 4698519b..39f5378e 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -17,8 +17,7 @@ Pod::Spec.new do |s| s.ios.source_files = 'Source/{iOS,Shared}/**/*' s.osx.source_files = 'Source/{Mac,Shared}/**/*' s.tvos.source_files = 'Source/{iOS,Shared}/**/*' - s.resources = 'Source/PrivacyInfo.xcprivacy' - + s.resource_bundles = { 'Cache_privacy' => 'Source/PrivacyInfo.xcprivacy' } s.frameworks = 'Foundation' s.swift_version = '5.0' end From 5b044183d53831da7a69682ad24b8ff05efa9e10 Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Thu, 18 Jul 2024 12:56:40 +0100 Subject: [PATCH 67/73] Set attributes of files created --- Source/Shared/Storage/DiskStorage.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index 78d9b733..c47be1fd 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -17,9 +17,11 @@ final public class DiskStorage { private let transformer: Transformer private let hasher = Hasher.constantAccrossExecutions() + private var defaultFileAttributes: [FileAttributeKey : Any]? // MARK: - Initialization - public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { + public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer, + fileAttributes: [FileAttributeKey : Any] = [:]) throws { let url: URL if let directory = config.directory { url = directory @@ -44,6 +46,9 @@ final public class DiskStorage { FileAttributeKey.protectionKey: protectionType ]) } + + defaultFileAttributes = fileAttributes + } public required init(config: DiskConfig, fileManager: FileManager = FileManager.default, path: String, transformer: Transformer) { @@ -80,8 +85,11 @@ extension DiskStorage: StorageAware { let expiry = expiry ?? config.expiry let data = try transformer.toData(object) let filePath = makeFilePath(for: key) - _ = fileManager.createFile(atPath: filePath, contents: data, attributes: nil) - try fileManager.setAttributes([.modificationDate: expiry.date], ofItemAtPath: filePath) + var attributes = defaultFileAttributes! + attributes[.modificationDate] = expiry.date + + _ = fileManager.createFile(atPath: filePath, contents: data, attributes: attributes) +// try fileManager.setAttributes([.modificationDate: expiry.date], ofItemAtPath: filePath) } public func removeObject(forKey key: Key) throws { From db45d9f4b1a7b80df1b96adb168861126b7983d0 Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Thu, 18 Jul 2024 13:21:51 +0100 Subject: [PATCH 68/73] Use FileManager instead of attributes. --- Source/Shared/Storage/DiskStorage.swift | 17 ++++++++--------- Source/Shared/Storage/Storage.swift | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index c47be1fd..a5c68167 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -17,11 +17,10 @@ final public class DiskStorage { private let transformer: Transformer private let hasher = Hasher.constantAccrossExecutions() - private var defaultFileAttributes: [FileAttributeKey : Any]? +// private var defaultFileAttributes: [FileAttributeKey : Any]? // MARK: - Initialization - public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer, - fileAttributes: [FileAttributeKey : Any] = [:]) throws { + public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { let url: URL if let directory = config.directory { url = directory @@ -47,7 +46,7 @@ final public class DiskStorage { ]) } - defaultFileAttributes = fileAttributes +// defaultFileAttributes = fileAttributes } @@ -85,11 +84,11 @@ extension DiskStorage: StorageAware { let expiry = expiry ?? config.expiry let data = try transformer.toData(object) let filePath = makeFilePath(for: key) - var attributes = defaultFileAttributes! - attributes[.modificationDate] = expiry.date - - _ = fileManager.createFile(atPath: filePath, contents: data, attributes: attributes) -// try fileManager.setAttributes([.modificationDate: expiry.date], ofItemAtPath: filePath) +// var attributes = defaultFileAttributes! +// attributes[.modificationDate] = expiry.date +// + _ = fileManager.createFile(atPath: filePath, contents: data, attributes: nil) + try fileManager.setAttributes([.modificationDate: expiry.date], ofItemAtPath: filePath) } public func removeObject(forKey key: Key) throws { diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index 12b567f1..4f94c86f 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -15,8 +15,8 @@ public final class Storage { /// - diskConfig: Configuration for disk storage /// - memoryConfig: Optional. Pass config if you want memory cache /// - Throws: Throw StorageError if any. - public convenience init(diskConfig: DiskConfig, memoryConfig: MemoryConfig, transformer: Transformer) throws { - let disk = try DiskStorage(config: diskConfig, transformer: transformer) + public convenience init(diskConfig: DiskConfig, memoryConfig: MemoryConfig, fileManager: FileManager, transformer: Transformer) throws { + let disk = try DiskStorage(config: diskConfig, fileManager: fileManager, transformer: transformer) let memory = MemoryStorage(config: memoryConfig) let hybridStorage = HybridStorage(memoryStorage: memory, diskStorage: disk) self.init(hybridStorage: hybridStorage) From e2a8f2f01e8755d2d70ac4c082a24ef0ecf0de84 Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Thu, 18 Jul 2024 14:01:28 +0100 Subject: [PATCH 69/73] Remove unused code. --- Source/Shared/Storage/DiskStorage.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index a5c68167..7bc36b6a 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -17,7 +17,6 @@ final public class DiskStorage { private let transformer: Transformer private let hasher = Hasher.constantAccrossExecutions() -// private var defaultFileAttributes: [FileAttributeKey : Any]? // MARK: - Initialization public convenience init(config: DiskConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { @@ -84,9 +83,6 @@ extension DiskStorage: StorageAware { let expiry = expiry ?? config.expiry let data = try transformer.toData(object) let filePath = makeFilePath(for: key) -// var attributes = defaultFileAttributes! -// attributes[.modificationDate] = expiry.date -// _ = fileManager.createFile(atPath: filePath, contents: data, attributes: nil) try fileManager.setAttributes([.modificationDate: expiry.date], ofItemAtPath: filePath) } From ddce7b991650422444a4cae19f47a8e1081188a3 Mon Sep 17 00:00:00 2001 From: Ken Carroll Date: Thu, 18 Jul 2024 14:15:11 +0100 Subject: [PATCH 70/73] Delete commented line of code. --- Source/Shared/Storage/DiskStorage.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index 7bc36b6a..78d9b733 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -44,9 +44,6 @@ final public class DiskStorage { FileAttributeKey.protectionKey: protectionType ]) } - -// defaultFileAttributes = fileAttributes - } public required init(config: DiskConfig, fileManager: FileManager = FileManager.default, path: String, transformer: Transformer) { From c07b1b8a9ebb9bdfbf9276a95435e8b625a030ed Mon Sep 17 00:00:00 2001 From: Lucas Romano Date: Tue, 27 Aug 2024 16:16:37 -0300 Subject: [PATCH 71/73] Update Cache.podspec --- Cache.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cache.podspec b/Cache.podspec index 39f5378e..c338e030 100644 --- a/Cache.podspec +++ b/Cache.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Cache" s.summary = "Nothing but cache." - s.version = "7.1.0" + s.version = "7.4.0" s.homepage = "https://github.com/hyperoslo/Cache" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } From bb7a3b7b090ec3614ca92f3eb847bdf742f722dd Mon Sep 17 00:00:00 2001 From: gibachan Date: Tue, 17 Dec 2024 09:24:08 +0900 Subject: [PATCH 72/73] Fix unit test --- Tests/iOS/Tests/Storage/StorageTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/iOS/Tests/Storage/StorageTests.swift b/Tests/iOS/Tests/Storage/StorageTests.swift index 80f3f18e..ec5e9ea2 100644 --- a/Tests/iOS/Tests/Storage/StorageTests.swift +++ b/Tests/iOS/Tests/Storage/StorageTests.swift @@ -2,6 +2,7 @@ import XCTest @testable import Cache final class StorageTests: XCTestCase { + private let fileManager = FileManager() private var storage: Storage! let user = User(firstName: "John", lastName: "Snow") @@ -11,6 +12,7 @@ final class StorageTests: XCTestCase { storage = try! Storage( diskConfig: DiskConfig(name: "Thor"), memoryConfig: MemoryConfig(), + fileManager: fileManager, transformer: TransformerFactory.forCodable(ofType: User.self) ) } From 12c81c30c177c7b73fe74ede562f41a40dee5ef6 Mon Sep 17 00:00:00 2001 From: Mack Hasz Date: Thu, 28 Aug 2025 16:28:29 -0400 Subject: [PATCH 73/73] Update Storage.swift --- Source/Shared/Storage/Storage.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index 4f94c86f..c6799cd4 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -15,7 +15,7 @@ public final class Storage { /// - diskConfig: Configuration for disk storage /// - memoryConfig: Optional. Pass config if you want memory cache /// - Throws: Throw StorageError if any. - public convenience init(diskConfig: DiskConfig, memoryConfig: MemoryConfig, fileManager: FileManager, transformer: Transformer) throws { + public convenience init(diskConfig: DiskConfig, memoryConfig: MemoryConfig, fileManager: FileManager = FileManager.default, transformer: Transformer) throws { let disk = try DiskStorage(config: diskConfig, fileManager: fileManager, transformer: transformer) let memory = MemoryStorage(config: memoryConfig) let hybridStorage = HybridStorage(memoryStorage: memory, diskStorage: disk)