diff --git a/Examples/iOS/Example.xcodeproj/project.pbxproj b/Examples/iOS/Example.xcodeproj/project.pbxproj index f28c6f7..cb2b0c3 100644 --- a/Examples/iOS/Example.xcodeproj/project.pbxproj +++ b/Examples/iOS/Example.xcodeproj/project.pbxproj @@ -26,7 +26,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 1B15D4F926902C2800CDECF2 /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = ""; }; + 1B15D4F926902C2800CDECF2 /* Defaults.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = ""; tabWidth = 2; }; 1B2EFF2823EEFA5800B5681B /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1B2EFF2B23EEFA5800B5681B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 1B2EFF2F23EEFA5800B5681B /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -42,7 +42,7 @@ 1B920D972732035A00B4BC5C /* movies.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = movies.json; sourceTree = ""; }; 1B920D992732036500B4BC5C /* Movie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Movie.swift; sourceTree = ""; }; 1B920D9B273203F700B4BC5C /* MoviesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoviesViewModel.swift; sourceTree = ""; }; - 1B920D9D2732085C00B4BC5C /* MoviesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoviesViewController.swift; sourceTree = ""; }; + 1B920D9D2732085C00B4BC5C /* MoviesViewController.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = MoviesViewController.swift; sourceTree = ""; tabWidth = 2; }; 5C22F2D044348A0F30859CA3 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; 81EDFF1C160A8EE85705B8E4 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9B3FE31FB59E0D9A03A7E93A /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; diff --git a/Examples/iOS/Example/Common/Defaults.swift b/Examples/iOS/Example/Common/Defaults.swift index 7baa4c8..e08b946 100644 --- a/Examples/iOS/Example/Common/Defaults.swift +++ b/Examples/iOS/Example/Common/Defaults.swift @@ -9,9 +9,12 @@ import LMStorage struct MyDefaults: LMDefaults { + static var suiteName: String? = "com.myApp.example" + enum Keys: String { case currentUser case accessToken case haveSeenOnboarding + case selectedMovie } } diff --git a/Examples/iOS/Example/Sections/Movies/View/MoviesViewController.swift b/Examples/iOS/Example/Sections/Movies/View/MoviesViewController.swift index fac8bc7..8e44f99 100644 --- a/Examples/iOS/Example/Sections/Movies/View/MoviesViewController.swift +++ b/Examples/iOS/Example/Sections/Movies/View/MoviesViewController.swift @@ -18,6 +18,9 @@ class MoviesViewController: UIViewController { // MARK: - View LifeCycle override func viewDidLoad() { super.viewDidLoad() + + print("Selected Movie: \(MyDefaults.value(forKey: .selectedMovie) as? String ?? "nil")") + viewModel.fetchMovies() } } @@ -48,5 +51,9 @@ extension MoviesViewController: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) + + let item = viewModel.movies[indexPath.row] + + MyDefaults.set(item.title, forKey: .selectedMovie) } } diff --git a/Examples/iOS/Podfile.lock b/Examples/iOS/Podfile.lock index 437a126..b376571 100644 --- a/Examples/iOS/Podfile.lock +++ b/Examples/iOS/Podfile.lock @@ -20,4 +20,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 208c4e2d0bc43c26e11d7fc08d1151f5fc532b17 -COCOAPODS: 1.10.2 +COCOAPODS: 1.16.2 diff --git a/Examples/tvOS/Example.xcodeproj/project.pbxproj b/Examples/tvOS/Example.xcodeproj/project.pbxproj index e38fd71..1dbe15b 100644 --- a/Examples/tvOS/Example.xcodeproj/project.pbxproj +++ b/Examples/tvOS/Example.xcodeproj/project.pbxproj @@ -27,7 +27,7 @@ 1BBE0FC8269406320060A38F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 1BBE0FCB269406320060A38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 1BBE0FCD269406320060A38F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1BF64C56269407150085A02D /* MyDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyDefaults.swift; sourceTree = ""; }; + 1BF64C56269407150085A02D /* MyDefaults.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = MyDefaults.swift; sourceTree = ""; tabWidth = 2; }; 1BF64C59269408020085A02D /* ViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = ""; }; 1BF64C5B269408020085A02D /* UserStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserStorage.swift; sourceTree = ""; }; 1BF64C5C269408020085A02D /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; diff --git a/Examples/tvOS/Example/MyDefaults.swift b/Examples/tvOS/Example/MyDefaults.swift index 9677bbc..74bf1a2 100644 --- a/Examples/tvOS/Example/MyDefaults.swift +++ b/Examples/tvOS/Example/MyDefaults.swift @@ -8,6 +8,8 @@ import LMStorage struct MyDefaults: LMDefaults { + static var suiteName: String? = "com.myApp.example" + enum Keys: String { case container = "Example" case user = "User" diff --git a/Examples/tvOS/Podfile.lock b/Examples/tvOS/Podfile.lock index 437a126..b376571 100644 --- a/Examples/tvOS/Podfile.lock +++ b/Examples/tvOS/Podfile.lock @@ -20,4 +20,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 208c4e2d0bc43c26e11d7fc08d1151f5fc532b17 -COCOAPODS: 1.10.2 +COCOAPODS: 1.16.2 diff --git a/Gemfile.lock b/Gemfile.lock index 3dc8252..da3ad3e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,11 +1,9 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.7) - base64 - nkf - rexml - activesupport (7.2.2.1) + CFPropertyList (3.0.8) + abbrev (0.1.2) + activesupport (7.2.3) base64 benchmark (>= 0.3) bigdecimal @@ -17,35 +15,36 @@ GEM minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) + addressable (2.8.8) + public_suffix (>= 2.0.2, < 8.0) algoliasearch (1.27.5) httpclient (~> 2.8, >= 2.8.3) json (>= 1.5.1) artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.4.0) - aws-partitions (1.1113.0) - aws-sdk-core (3.225.1) + aws-partitions (1.1205.0) + aws-sdk-core (3.241.3) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) base64 + bigdecimal jmespath (~> 1, >= 1.6.1) logger - aws-sdk-kms (1.104.0) - aws-sdk-core (~> 3, >= 3.225.0) + aws-sdk-kms (1.120.0) + aws-sdk-core (~> 3, >= 3.241.3) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.189.0) - aws-sdk-core (~> 3, >= 3.225.0) + aws-sdk-s3 (1.211.0) + aws-sdk-core (~> 3, >= 3.241.3) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.12.0) + aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) - base64 (0.3.0) - benchmark (0.4.1) - bigdecimal (3.2.2) + base64 (0.2.0) + benchmark (0.5.0) + bigdecimal (4.0.1) claide (1.1.0) cocoapods (1.16.2) addressable (~> 2.8) @@ -88,8 +87,9 @@ GEM colored2 (3.1.2) commander (4.6.0) highline (~> 2.0.0) - concurrent-ruby (1.3.5) - connection_pool (2.5.3) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) + csv (3.3.5) declarative (0.0.20) digest-crc (0.7.0) rake (>= 12.0.0, < 14.0.0) @@ -98,8 +98,9 @@ GEM drb (2.2.3) emoji_regex (3.2.3) escape (0.0.4) - ethon (0.16.0) + ethon (0.18.0) ffi (>= 1.15.0) + logger excon (0.112.0) faraday (1.10.4) faraday-em_http (~> 1.0) @@ -113,14 +114,14 @@ GEM faraday-rack (~> 1.0) faraday-retry (~> 1.0) ruby2_keywords (>= 0.0.4) - faraday-cookie_jar (0.0.7) + faraday-cookie_jar (0.0.8) faraday (>= 0.8.0) - http-cookie (~> 1.0.0) + http-cookie (>= 1.0.0) faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.0) + faraday-em_synchrony (1.0.1) faraday-excon (1.1.0) faraday-httpclient (1.0.1) - faraday-multipart (1.1.0) + faraday-multipart (1.2.0) multipart-post (~> 2.0) faraday-net_http (1.0.2) faraday-net_http_persistent (1.2.0) @@ -130,15 +131,18 @@ GEM faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.4.0) - fastlane (2.227.2) + fastlane (2.230.0) CFPropertyList (>= 2.3, < 4.0.0) + abbrev (~> 0.1.2) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) + base64 (~> 0.2.0) bundler (>= 1.12.0, < 3.0.0) colored (~> 1.2) commander (~> 4.6) + csv (~> 3.3) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) excon (>= 0.71.0, < 1.0.0) @@ -156,9 +160,12 @@ GEM http-cookie (~> 1.0.5) json (< 3.0.0) jwt (>= 2.1.0, < 3) + logger (>= 1.6, < 2.0) mini_magick (>= 4.9.4, < 5.0.0) multipart-post (>= 2.0.0, < 3.0.0) + mutex_m (~> 0.3.0) naturally (~> 2.2) + nkf (~> 0.2.0) optparse (>= 0.1.1, < 1.0.0) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) @@ -174,7 +181,7 @@ GEM xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) fastlane-sirp (1.0.0) sysrandom (~> 1.0) - ffi (1.17.2-arm64-darwin) + ffi (1.17.3-arm64-darwin) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) @@ -219,46 +226,48 @@ GEM domain_name (~> 0.5) httpclient (2.9.0) mutex_m - i18n (1.14.7) + i18n (1.14.8) concurrent-ruby (~> 1.0) jmespath (1.6.2) - json (2.12.2) - jwt (2.10.1) + json (2.18.0) + jwt (2.10.2) base64 logger (1.7.0) mini_magick (4.13.2) mini_mime (1.1.5) - minitest (5.25.5) + minitest (6.0.1) + prism (~> 1.5) molinillo (0.8.0) - multi_json (1.15.0) + multi_json (1.19.1) multipart-post (2.4.1) mutex_m (0.3.0) nanaimo (0.4.0) nap (1.1.0) - naturally (2.2.2) + naturally (2.3.0) netrc (0.11.0) nkf (0.2.0) - optparse (0.6.0) + optparse (0.8.1) os (1.1.4) plist (3.7.2) + prism (1.8.0) public_suffix (4.0.7) - rake (13.3.0) + rake (13.3.1) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.4.1) + rexml (3.4.4) rouge (3.28.0) ruby-macho (2.5.1) ruby2_keywords (0.0.5) rubyzip (2.4.1) securerandom (0.4.1) security (0.1.5) - signet (0.20.0) + signet (0.21.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) - jwt (>= 1.5, < 3.0) + jwt (>= 1.5, < 4.0) multi_json (~> 1.10) simctl (1.6.10) CFPropertyList @@ -301,4 +310,4 @@ DEPENDENCIES fastlane BUNDLED WITH - 2.6.9 + 2.7.2 diff --git a/Sources/LMStorage/LMDefaults.swift b/Sources/LMStorage/LMDefaults.swift index 44e1708..c39287e 100644 --- a/Sources/LMStorage/LMDefaults.swift +++ b/Sources/LMStorage/LMDefaults.swift @@ -25,6 +25,8 @@ import Foundation public protocol LMDefaults { associatedtype Keys: RawRepresentable where Keys.RawValue == String + static var suiteName: String? { get set } + static func set(_ value: Any?, forKey: Keys) static func set(array: [Any], key: Keys) static func set(array: [T], key: Keys) @@ -40,6 +42,7 @@ public protocol LMDefaults { } extension LMDefaults { + // MARK: - Public Methods /// Sets the value of the specified default key. /// - Parameters: @@ -114,20 +117,18 @@ extension LMDefaults { /// - Parameter key: A key in the current user‘s defaults database. /// - Returns: The array associated with the specified key, or nil if the key does not exist or its value is not an array. public static func array(forKey key: Keys) -> [Any]? { - UserDefaults.standard.array(forKey: key.rawValue) + defaults.array(forKey: key.rawValue) } /// Remove saved object using the constants key /// - Parameter key: The key with which to associate the value. public static func removeObject(forKey key: Keys) { - UserDefaults.standard.removeObject(forKey: key.rawValue) + defaults.removeObject(forKey: key.rawValue) } /// Reset defaults for some keys /// - Parameter keys: Keys to reset values public static func reset(for keys: [Keys]) { - let defaults = UserDefaults.standard - keys.forEach { key in defaults.removeObject(forKey: key.rawValue) } @@ -135,7 +136,6 @@ extension LMDefaults { /// Reset defaults public static func reset() { - let defaults = UserDefaults.standard let dictionary = defaults.dictionaryRepresentation() dictionary.keys.forEach { key in @@ -144,11 +144,18 @@ extension LMDefaults { } // MARK: - Private Methods + private static var defaults: UserDefaults { + if let suiteName { + return UserDefaults(suiteName: suiteName) ?? UserDefaults.standard + } + return UserDefaults.standard + } + private static func value(forKey key: String) -> Any? { - UserDefaults.standard.value(forKey: key) + defaults.value(forKey: key) } private static func set(data: Any?, forKey: String) { - UserDefaults.standard.set(data, forKey: forKey) + defaults.set(data, forKey: forKey) } } diff --git a/Tests/LMStorageTests/Mock/DefaultsMock.swift b/Tests/LMStorageTests/Mock/DefaultsMock.swift index af818b1..314826c 100644 --- a/Tests/LMStorageTests/Mock/DefaultsMock.swift +++ b/Tests/LMStorageTests/Mock/DefaultsMock.swift @@ -23,6 +23,8 @@ @testable import LMStorage struct DefaultsMock: LMDefaults { + static var suiteName: String? + enum Keys: String { case currentUser case accessToken