diff --git a/FirebaseMLModelDownloader.podspec b/FirebaseMLModelDownloader.podspec index f3a493b4cd1..16724bb2972 100644 --- a/FirebaseMLModelDownloader.podspec +++ b/FirebaseMLModelDownloader.podspec @@ -40,7 +40,8 @@ Pod::Spec.new do |s| s.dependency 'FirebaseInstallations', '~> 10.0' s.dependency 'GoogleDataTransport', '~> 9.2' # TODO: Revisit this dependency - s.dependency 'GoogleUtilities/Logger', '~> 7.8' + s.dependency 'GoogleUtilities/Logger', '~> 7.13' + s.dependency 'GoogleUtilities/UserDefaults', '~> 7.13' s.dependency 'SwiftProtobuf', '~> 1.19' s.pod_target_xcconfig = { diff --git a/FirebaseMLModelDownloader/Sources/DeviceLogger.swift b/FirebaseMLModelDownloader/Sources/DeviceLogger.swift index 1cfece5af33..fc82b225414 100644 --- a/FirebaseMLModelDownloader/Sources/DeviceLogger.swift +++ b/FirebaseMLModelDownloader/Sources/DeviceLogger.swift @@ -14,9 +14,9 @@ import Foundation #if SWIFT_PACKAGE - import GoogleUtilities_Logger + @_implementationOnly import GoogleUtilities_Logger #else - import GoogleUtilities + @_implementationOnly import GoogleUtilities #endif /// Enum of log messages. diff --git a/FirebaseMLModelDownloader/Sources/DownloaderUserDefaults.swift b/FirebaseMLModelDownloader/Sources/DownloaderUserDefaults.swift index 0f7453de364..1f66bf8a0b2 100644 --- a/FirebaseMLModelDownloader/Sources/DownloaderUserDefaults.swift +++ b/FirebaseMLModelDownloader/Sources/DownloaderUserDefaults.swift @@ -13,9 +13,14 @@ // limitations under the License. import Foundation +#if SWIFT_PACKAGE + @_implementationOnly import GoogleUtilities_UserDefaults +#else + @_implementationOnly import GoogleUtilities +#endif // SWIFT_PACKAGE /// Protocol to save or delete model info in user defaults. protocol DownloaderUserDefaultsWriteable { - func writeToDefaults(_ defaults: UserDefaults, appName: String) - func removeFromDefaults(_ defaults: UserDefaults, appName: String) + func writeToDefaults(_ defaults: GULUserDefaults, appName: String) + func removeFromDefaults(_ defaults: GULUserDefaults, appName: String) } diff --git a/FirebaseMLModelDownloader/Sources/LocalModelInfo.swift b/FirebaseMLModelDownloader/Sources/LocalModelInfo.swift index 96e2b8aee3a..5c51c5fded8 100644 --- a/FirebaseMLModelDownloader/Sources/LocalModelInfo.swift +++ b/FirebaseMLModelDownloader/Sources/LocalModelInfo.swift @@ -13,6 +13,11 @@ // limitations under the License. import Foundation +#if SWIFT_PACKAGE + @_implementationOnly import GoogleUtilities_UserDefaults +#else + @_implementationOnly import GoogleUtilities +#endif // SWIFT_PACKAGE /// Model info object with details about downloaded and locally available model. class LocalModelInfo { @@ -41,7 +46,7 @@ class LocalModelInfo { } /// Convenience init to create local model info from stored info in user defaults. - convenience init?(fromDefaults defaults: UserDefaults, name: String, appName: String) { + convenience init?(fromDefaults defaults: GULUserDefaults, name: String, appName: String) { let defaultsPrefix = LocalModelInfo.getUserDefaultsKeyPrefix(appName: appName, modelName: name) guard let modelHash = defaults.string(forKey: "\(defaultsPrefix).model-hash") else { return nil @@ -60,13 +65,13 @@ extension LocalModelInfo: DownloaderUserDefaultsWriteable { } /// Write local model info to user defaults. - func writeToDefaults(_ defaults: UserDefaults, appName: String) { + func writeToDefaults(_ defaults: GULUserDefaults, appName: String) { let defaultsPrefix = LocalModelInfo.getUserDefaultsKeyPrefix(appName: appName, modelName: name) - defaults.setValue(modelHash, forKey: "\(defaultsPrefix).model-hash") - defaults.setValue(size, forKey: "\(defaultsPrefix).model-size") + defaults.setObject(modelHash, forKey: "\(defaultsPrefix).model-hash") + defaults.setObject(size, forKey: "\(defaultsPrefix).model-size") } - func removeFromDefaults(_ defaults: UserDefaults, appName: String) { + func removeFromDefaults(_ defaults: GULUserDefaults, appName: String) { let defaultsPrefix = LocalModelInfo.getUserDefaultsKeyPrefix(appName: appName, modelName: name) defaults.removeObject(forKey: "\(defaultsPrefix).model-hash") defaults.removeObject(forKey: "\(defaultsPrefix).model-size") @@ -74,12 +79,8 @@ extension LocalModelInfo: DownloaderUserDefaultsWriteable { } /// Named user defaults for FirebaseML. -extension UserDefaults { - static var firebaseMLDefaults: UserDefaults { - let suiteName = "com.google.firebase.ml" - guard let defaults = UserDefaults(suiteName: suiteName) else { - return UserDefaults.standard - } - return defaults +extension GULUserDefaults { + static var firebaseMLDefaults: GULUserDefaults { + return GULUserDefaults(suiteName: "com.google.firebase.ml") } } diff --git a/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift b/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift index 05256933f29..c0f218bfd9e 100644 --- a/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift +++ b/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift @@ -13,6 +13,11 @@ // limitations under the License. import Foundation +#if SWIFT_PACKAGE + @_implementationOnly import GoogleUtilities_UserDefaults +#else + @_implementationOnly import GoogleUtilities +#endif // SWIFT_PACKAGE /// Task to download model file to device. class ModelDownloadTask { @@ -23,7 +28,7 @@ class ModelDownloadTask { private(set) var remoteModelInfo: RemoteModelInfo /// User defaults to which local model info should ultimately be written. - private let defaults: UserDefaults + private let defaults: GULUserDefaults /// Keeps track of download associated with this model download task. private(set) var downloadStatus: ModelDownloadStatus = .ready @@ -44,7 +49,7 @@ class ModelDownloadTask { init(remoteModelInfo: RemoteModelInfo, appName: String, - defaults: UserDefaults, + defaults: GULUserDefaults, downloader: FileDownloader, progressHandler: ProgressHandler? = nil, completion: @escaping Completion, diff --git a/FirebaseMLModelDownloader/Sources/ModelDownloader.swift b/FirebaseMLModelDownloader/Sources/ModelDownloader.swift index 2f66f0b887e..ba5e047757b 100644 --- a/FirebaseMLModelDownloader/Sources/ModelDownloader.swift +++ b/FirebaseMLModelDownloader/Sources/ModelDownloader.swift @@ -15,6 +15,11 @@ import FirebaseCore import FirebaseInstallations import Foundation +#if SWIFT_PACKAGE + @_implementationOnly import GoogleUtilities_UserDefaults +#else + @_implementationOnly import GoogleUtilities +#endif // SWIFT_PACKAGE /// Possible ways to get a custom model. public enum ModelDownloadType { @@ -41,7 +46,7 @@ public class ModelDownloader { private let installations: Installations /// User defaults for model info. - private let userDefaults: UserDefaults + private let userDefaults: GULUserDefaults /// Telemetry logger tied to this instance of model downloader. let telemetryLogger: TelemetryLogger? @@ -67,7 +72,7 @@ public class ModelDownloader { } /// Private init for model downloader. - private init(app: FirebaseApp, defaults: UserDefaults = .firebaseMLDefaults) { + private init(app: FirebaseApp, defaults: GULUserDefaults = .firebaseMLDefaults) { appName = app.name options = app.options installations = Installations.installations(app: app) @@ -641,7 +646,7 @@ extension ModelDownloader { /// Model downloader extension for testing. extension ModelDownloader { /// Model downloader instance for testing. - static func modelDownloaderWithDefaults(_ defaults: UserDefaults, + static func modelDownloaderWithDefaults(_ defaults: GULUserDefaults, app: FirebaseApp) -> ModelDownloader { let downloader = ModelDownloader(app: app, defaults: defaults) return downloader diff --git a/FirebaseMLModelDownloader/Tests/Integration/ModelDownloaderIntegrationTests.swift b/FirebaseMLModelDownloader/Tests/Integration/ModelDownloaderIntegrationTests.swift index 32d512334d6..6d5a9a83893 100644 --- a/FirebaseMLModelDownloader/Tests/Integration/ModelDownloaderIntegrationTests.swift +++ b/FirebaseMLModelDownloader/Tests/Integration/ModelDownloaderIntegrationTests.swift @@ -22,20 +22,26 @@ @testable import FirebaseInstallations @testable import FirebaseMLModelDownloader import XCTest - - extension UserDefaults { - /// Returns a new cleared instance of user defaults. - static func createTestInstance(testName: String) -> UserDefaults { + #if SWIFT_PACKAGE + @_implementationOnly import GoogleUtilities_UserDefaults + #else + @_implementationOnly import GoogleUtilities + #endif // SWIFT_PACKAGE + + extension GULUserDefaults { + /// Returns an instance of user defaults. + static func createTestInstance(testName: String) -> GULUserDefaults { let suiteName = "com.google.firebase.ml.test.\(testName)" - let defaults = UserDefaults(suiteName: suiteName)! - defaults.removePersistentDomain(forName: suiteName) - return defaults + // Clear the suite (`UserDefaults` and `GULUserDefaults` map to the same + // storage space and `GULUserDefaults` doesn't offer API to do this.) + UserDefaults(suiteName: suiteName)!.removePersistentDomain(forName: suiteName) + return GULUserDefaults(suiteName: suiteName) } /// Returns the existing user defaults instance. - static func getTestInstance(testName: String) -> UserDefaults { + static func getTestInstance(testName: String) -> GULUserDefaults { let suiteName = "com.google.firebase.ml.test.\(testName)" - return UserDefaults(suiteName: suiteName)! + return GULUserDefaults(suiteName: suiteName) } } diff --git a/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift b/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift index 4a1be379336..b7bec11c323 100644 --- a/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift +++ b/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift @@ -22,6 +22,12 @@ @testable import FirebaseInstallations @testable import FirebaseMLModelDownloader import XCTest + #if SWIFT_PACKAGE + @_implementationOnly import GoogleUtilities_Logger + @_implementationOnly import GoogleUtilities_UserDefaults + #else + @_implementationOnly import GoogleUtilities + #endif // SWIFT_PACKAGE /// Mock options to configure default Firebase app. private enum MockOptions { @@ -1325,19 +1331,18 @@ } } - extension UserDefaults { - /// Returns a new cleared instance of user defaults. - static func createUnitTestInstance(testName: String) -> UserDefaults { + extension GULUserDefaults { + /// Returns a new instance of user defaults. + static func createUnitTestInstance(testName: String) -> GULUserDefaults { let suiteName = "com.google.firebase.ml.test.\(testName)" - let defaults = UserDefaults(suiteName: suiteName)! - defaults.removePersistentDomain(forName: suiteName) + let defaults = GULUserDefaults(suiteName: suiteName) return defaults } /// Returns the existing user defaults instance. - static func getUnitTestInstance(testName: String) -> UserDefaults { + static func getUnitTestInstance(testName: String) -> GULUserDefaults { let suiteName = "com.google.firebase.ml.test.\(testName)" - return UserDefaults(suiteName: suiteName)! + return GULUserDefaults(suiteName: suiteName) } } diff --git a/Package.swift b/Package.swift index 44150f5e561..f841c96a37a 100644 --- a/Package.swift +++ b/Package.swift @@ -838,6 +838,7 @@ let package = Package( "FirebaseInstallations", .product(name: "GoogleDataTransport", package: "GoogleDataTransport"), .product(name: "GULLogger", package: "GoogleUtilities"), + .product(name: "GULUserDefaults", package: "GoogleUtilities"), .product(name: "SwiftProtobuf", package: "swift-protobuf"), ], path: "FirebaseMLModelDownloader/Sources",