Skip to content

Commit d4d2cf1

Browse files
committed
[Config] Follow-up to #14309
1 parent ccfc844 commit d4d2cf1

File tree

3 files changed

+61
-67
lines changed

3 files changed

+61
-67
lines changed

FirebaseRemoteConfig/SwiftNew/ConfigContent.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class ConfigContent: NSObject {
165165
dispatchGroup.enter()
166166
dbManager.loadMain(withBundleIdentifier: bundleIdentifier) { [weak self] success,
167167
fetched, active, defaults, rolloutMetadata in
168-
guard let self = self else { return }
168+
guard let self else { return }
169169
self._fetchedConfig.store(newValue: fetched)
170170
self._activeConfig.store(newValue: active)
171171
self._defaultConfig.store(newValue: defaults)
@@ -182,7 +182,7 @@ class ConfigContent: NSObject {
182182
dispatchGroup.enter()
183183
dbManager.loadPersonalization { [weak self] success, fetchedPersonalization,
184184
activePersonalization in
185-
guard let self = self else { return }
185+
guard let self else { return }
186186
self._fetchedPersonalization = fetchedPersonalization
187187
self._activePersonalization = activePersonalization
188188
self.dispatchGroup.leave()

FirebaseRemoteConfig/SwiftNew/ConfigRealtime.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ class ConfigRealtime: NSObject, URLSessionDataDelegate {
224224

225225
RCLog.debug("I-RCN000039", "Starting requesting token.")
226226
installations.authToken { [weak self] result, error in
227-
guard let self = self else { return }
227+
guard let self else { return }
228228
if let error = error {
229229
let errorDescription = "Failed to get installations token. Error : \(error)."
230230
RCLog.error("I-RCN000073", errorDescription)
@@ -257,7 +257,7 @@ class ConfigRealtime: NSObject, URLSessionDataDelegate {
257257
}
258258
/// We have a valid token. Get the backing installationID.
259259
installations.installationID { [weak self] identifier, error in
260-
guard let self = self else { return }
260+
guard let self else { return }
261261
// Dispatch to the RC serial queue to update settings on the queue.
262262
self.realtimeLockQueue.async {
263263
/// Update config settings with the IID and token.

FirebaseRemoteConfig/SwiftNew/RemoteConfig.swift

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
430430
}
431431

432432
/// Adds a listener that will be called whenever one of the get methods is called.
433-
/// - Parameter listener Function that takes in the parameter key and the config.
433+
/// - Parameter listener: Function that takes in the parameter key and the config.
434434
@objc public func addListener(_ listener: @escaping RemoteConfigListener) {
435435
queue.async {
436436
self.listeners.append(listener)
@@ -478,7 +478,7 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
478478
/// To stop the periodic sync, call `Installations.delete(completion:)`
479479
/// and avoid calling this method again.
480480
///
481-
/// - Parameter completionHandler Fetch operation callback with status and error parameters.
481+
/// - Parameter completionHandler: Fetch operation callback with status and error parameters.
482482
@objc public func fetch(completionHandler: (
483483
@Sendable (RemoteConfigFetchStatus, Error?) -> Void
484484
)? =
@@ -492,7 +492,7 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
492492
/// Fetches Remote Config data and sets a duration that specifies how long config data lasts.
493493
/// Call `activateWithCompletion:` to make fetched data available to your app.
494494
///
495-
/// - Parameter expirationDuration Override the (default or optionally set `minimumFetchInterval`
495+
/// - Parameter expirationDuration: Override the (default or optionally set `minimumFetchInterval`
496496
/// property in RemoteConfigSettings) `minimumFetchInterval` for only the current request, in
497497
/// seconds. Setting a value of 0 seconds will force a fetch to the backend.
498498
///
@@ -518,10 +518,10 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
518518
/// Fetches Remote Config data and sets a duration that specifies how long config data lasts.
519519
/// Call `activateWithCompletion:` to make fetched data available to your app.
520520
///
521-
/// - Parameter expirationDuration Override the (default or optionally set `minimumFetchInterval`
521+
/// - Parameter expirationDuration: Override the (default or optionally set `minimumFetchInterval`
522522
/// property in RemoteConfigSettings) `minimumFetchInterval` for only the current request, in
523523
/// seconds. Setting a value of 0 seconds will force a fetch to the backend.
524-
/// - Parameter completionHandler Fetch operation callback with status and error parameters.
524+
/// - Parameter completionHandler: Fetch operation callback with status and error parameters.
525525
///
526526
/// Note: This method uses a Firebase Installations token to identify the app instance, and once
527527
/// it's called, it periodically sends data to the Firebase backend. (see
@@ -550,12 +550,14 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
550550
/// and avoid calling this method again.
551551
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
552552
public func fetchAndActivate() async throws -> RemoteConfigFetchAndActivateStatus {
553-
_ = try await fetch()
554-
do {
555-
try await activate()
556-
return .successFetchedFromRemote
557-
} catch {
558-
return .successUsingPreFetchedData
553+
return try await withUnsafeThrowingContinuation { continuation in
554+
fetchAndActivate { status, error in
555+
if let error {
556+
continuation.resume(throwing: error)
557+
} else {
558+
continuation.resume(returning: status)
559+
}
560+
}
559561
}
560562
}
561563

@@ -569,7 +571,7 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
569571
/// To stop the periodic sync, call `Installations.delete(completion:)`
570572
/// and avoid calling this method again.
571573
///
572-
/// - Parameter completionHandler Fetch operation callback with status and error parameters.
574+
/// - Parameter completionHandler: Fetch operation callback with status and error parameters.
573575
@objc public func fetchAndActivate(completionHandler:
574576
(@Sendable (RemoteConfigFetchAndActivateStatus, Error?) -> Void)? = nil) {
575577
fetch { [weak self] fetchStatus, error in
@@ -617,7 +619,7 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
617619

618620
/// Applies Fetched Config data to the Active Config, causing updates to the behavior and
619621
/// appearance of the app to take effect (depending on how config data is used in the app).
620-
/// - Parameter completion Activate operation callback with changed and error parameters.
622+
/// - Parameter completion: Activate operation callback with changed and error parameters.
621623
@objc public func activate(completion: (@Sendable (Bool, Error?) -> Void)? = nil) {
622624
queue.async { [weak self] in
623625
guard let self else {
@@ -626,12 +628,12 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
626628
code: RemoteConfigError.internalError.rawValue,
627629
userInfo: ["ActivationFailureReason": "Internal Error."]
628630
)
629-
RCLog.error("I-RCN000068", "Internal error activating config.")
630631
if let completion {
631632
DispatchQueue.main.async {
632633
completion(false, error)
633634
}
634635
}
636+
RCLog.error("I-RCN000068", "Internal error activating config.")
635637
return
636638
}
637639
// Check if the last fetched config has already been activated. Fetches with no data change
@@ -695,7 +697,7 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
695697
)
696698
}
697699

698-
// MARK: helpers
700+
// MARK: - Helpers
699701

700702
private func fullyQualifiedNamespace(_ namespace: String) -> String {
701703
if namespace.contains(":") { return namespace } // Already fully qualified
@@ -713,114 +715,106 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
713715
// MARK: Get Config Result
714716

715717
/// Gets the config value.
716-
/// - Parameter key Config key.
718+
/// - Parameter key: Config key.
717719
@objc public func configValue(forKey key: String) -> RemoteConfigValue {
718720
guard !key.isEmpty else {
719721
return RemoteConfigValue(data: Data(), source: .static)
720722
}
721723

722724
let fullyQualifiedNamespace = fullyQualifiedNamespace(FIRNamespace)
723-
var value: RemoteConfigValue!
724725

725-
queue.sync {
726-
value = configContent.activeConfig()[fullyQualifiedNamespace]?[key]
727-
if let value = value {
728-
if value.source != .remote {
729-
RCLog.error("I-RCN000001",
730-
"Key \(key) should come from source: \(RemoteConfigSource.remote.rawValue)" +
731-
"instead coming from source: \(value.source.rawValue)")
732-
}
733-
if let config = configContent.getConfigAndMetadata(forNamespace: fullyQualifiedNamespace)
734-
as? [String: RemoteConfigValue] {
735-
callListeners(key: key, config: config)
736-
}
737-
return
726+
return queue.sync {
727+
guard let value = configContent.activeConfig()[fullyQualifiedNamespace]?[key] else {
728+
return defaultValue(forFullyQualifiedNamespace: fullyQualifiedNamespace, key: key)
738729
}
739730

740-
value = defaultValue(forFullyQualifiedNamespace: fullyQualifiedNamespace, key: key)
731+
if value.source != .remote {
732+
RCLog.error("I-RCN000001",
733+
"Key \(key) should come from source: \(RemoteConfigSource.remote.rawValue)" +
734+
"instead coming from source: \(value.source.rawValue)")
735+
}
736+
if let config = configContent.getConfigAndMetadata(forNamespace: fullyQualifiedNamespace)
737+
as? [String: RemoteConfigValue] {
738+
callListeners(key: key, config: config)
739+
}
740+
return value
741741
}
742-
return value
743742
}
744743

745744
/// Gets the config value of a given source from the default namespace.
746-
/// - Parameter key Config key.
747-
/// - Parameter source Config value source.
745+
/// - Parameter key: Config key.
746+
/// - Parameter source: Config value source.
748747
@objc public func configValue(forKey key: String, source: RemoteConfigSource) ->
749748
RemoteConfigValue {
750749
guard !key.isEmpty else {
751750
return RemoteConfigValue(data: Data(), source: .static)
752751
}
753752
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
754-
var value: RemoteConfigValue!
755753

756-
queue.sync {
757-
switch source {
754+
return queue.sync {
755+
let remoteConfigValue = switch source {
758756
case .remote:
759-
value = configContent.activeConfig()[fullyQualifiedNamespace]?[key]
757+
configContent.activeConfig()[fullyQualifiedNamespace]?[key]
760758
case .default:
761-
value = configContent.defaultConfig()[fullyQualifiedNamespace]?[key]
759+
configContent.defaultConfig()[fullyQualifiedNamespace]?[key]
762760
case .static:
763-
value = RemoteConfigValue(data: Data(), source: .static)
761+
RemoteConfigValue(data: Data(), source: .static)
764762
}
763+
return remoteConfigValue ?? RemoteConfigValue(data: Data(), source: source)
765764
}
766-
return value
767765
}
768766

769767
@objc(allKeysFromSource:)
770768
public func allKeys(from source: RemoteConfigSource) -> [String] {
771-
var keys: [String] = []
772769
queue.sync {
773770
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
774771
switch source {
775772
case .default:
776773
if let values = configContent.defaultConfig()[fullyQualifiedNamespace] {
777-
keys = Array(values.keys)
774+
return Array(values.keys)
778775
}
779776
case .remote:
780777
if let values = configContent.activeConfig()[fullyQualifiedNamespace] {
781-
keys = Array(values.keys)
778+
return Array(values.keys)
782779
}
783-
case .static:
784-
break
780+
case .static: break
785781
}
782+
return []
786783
}
787-
return keys
788784
}
789785

790786
@objc public func keys(withPrefix prefix: String?) -> Set<String> {
791-
var keys = Set<String>()
792787
queue.sync {
793788
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
794789

795790
if let config = configContent.activeConfig()[fullyQualifiedNamespace] {
796791
if let prefix = prefix, !prefix.isEmpty {
797-
keys = Set(config.keys.filter { $0.hasPrefix(prefix) })
792+
return Set(config.keys.filter { $0.hasPrefix(prefix) })
798793
} else {
799-
keys = Set(config.keys)
794+
return Set(config.keys)
800795
}
801796
}
797+
return Set<String>()
802798
}
803-
return keys
804799
}
805800

806801
public func countByEnumerating(with state: UnsafeMutablePointer<NSFastEnumerationState>,
807802
objects buffer: AutoreleasingUnsafeMutablePointer<AnyObject?>,
808803
count len: Int) -> Int {
809-
var count = 0
810804
queue.sync {
811805
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
812806

813807
if let config = configContent.activeConfig()[fullyQualifiedNamespace] as? NSDictionary {
814-
count = config.countByEnumerating(with: state, objects: buffer, count: len)
808+
return config.countByEnumerating(with: state, objects: buffer, count: len)
815809
}
810+
return 0
816811
}
817-
return count
818812
}
819813

820814
// MARK: - Defaults
821815

822816
/// Sets config defaults for parameter keys and values in the default namespace config.
823-
/// - Parameter defaults A dictionary mapping a NSString * key to a NSObject * value.
817+
/// - Parameter defaults: A dictionary mapping a NSString * key to a NSObject * value.
824818
@objc public func setDefaults(_ defaults: [String: Any]?) {
825819
let defaults = defaults ?? [String: Any]()
826820
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
@@ -836,12 +830,12 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
836830

837831
/// Sets default configs from plist for default namespace.
838832
///
839-
/// - Parameter fileName The plist file name, with no file name extension. For example, if the
833+
/// - Parameter fileName: The plist file name, with no file name extension. For example, if the
840834
/// plist file is named `defaultSamples.plist`:
841835
/// `RemoteConfig.remoteConfig().setDefaults(fromPlist: "defaultSamples")`
842836
@objc(setDefaultsFromPlistFileName:)
843837
public func setDefaults(fromPlist fileName: String?) {
844-
guard let fileName = fileName, !fileName.isEmpty else {
838+
guard let fileName, !fileName.isEmpty else {
845839
RCLog.warning("I-RCN000037",
846840
"The plist file name cannot be nil or empty.")
847841
return
@@ -860,12 +854,12 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
860854

861855
/// Returns the default value of a given key from the default config.
862856
///
863-
/// - Parameter key The parameter key of default config.
857+
/// - Parameter key: The parameter key of default config.
864858
/// - Returns The default value of the specified key if the key exists; otherwise, nil.
865859
@objc public func defaultValue(forKey key: String) -> RemoteConfigValue? {
866-
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
867-
var value: RemoteConfigValue?
868860
queue.sync {
861+
let fullyQualifiedNamespace = self.fullyQualifiedNamespace(FIRNamespace)
862+
var value: RemoteConfigValue?
869863
if let config = configContent.defaultConfig()[fullyQualifiedNamespace] {
870864
value = config[key]
871865
if let value, value.source != .default {
@@ -874,8 +868,8 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
874868
"instead coming from source: \(value.source.rawValue)")
875869
}
876870
}
871+
return value
877872
}
878-
return value
879873
}
880874

881875
// MARK: Realtime
@@ -892,9 +886,9 @@ open class RemoteConfig: NSObject, NSFastEnumeration {
892886
/// https://firebase.google.com/docs/remote-config/get-started
893887
/// for more information.
894888
///
895-
/// - Parameter listener The configured listener that is called for every config
889+
/// - Parameter listener: The configured listener that is called for every config
896890
/// update.
897-
/// - Returns Returns a registration representing the listener. The registration
891+
/// - Returns A registration representing the listener. The registration
898892
/// contains a remove method, which can be used to stop receiving updates for the provided
899893
/// listener.
900894
@discardableResult

0 commit comments

Comments
 (0)