firebase-ios-sdk
firebase-ios-sdk copied to clipboard
Add AsyncStream support for Remote Config
This PR introduces a new configUpdates property to RemoteConfig, providing an AsyncThrowingStream for consuming real-time config updates. This offers a modern, Swift Concurrency-native alternative to the existing closure-based listener, making it easier to integrate real-time updates into async/await workflows.
Motivation
The existing addOnConfigUpdateListener uses a closure-based callback, which can be cumbersome in modern Swift applications that have adopted Swift Concurrency. By providing an AsyncThrowingStream, we offer a more ergonomic and idiomatic way for developers to receive real-time updates, simplifying their code and improving readability.
Implementation Details
-
FirebaseRemoteConfig/Swift/RemoteConfig+Async.swift: A new file containing an extension on RemoteConfig.- It adds a public configUpdates property that returns an AsyncThrowingStream<RemoteConfigUpdate, Error>.
- The stream's implementation wraps the existing addOnConfigUpdateListener.
- The listener's lifecycle is automatically managed: it is added when iteration begins and removed when the stream is terminated (e.g., through cancellation).
-
FirebaseRemoteConfig/Tests/Swift/SwiftAPI/AsyncStreamTests.swift: A new test suite for the async stream functionality.- Includes mock objects to simulate the real-time service and listener registration.
- Contains tests for various scenarios, including successful updates, error handling, stream cancellation, and handling of multiple updates.
Example usage
Developers can now listen for real-time updates using a simple for try await loop:
func listenForRealtimeUpdates() {
Task {
do {
for try await configUpdate in remoteConfig.configUpdates {
print("Updated keys: \(configUpdate.updatedKeys)")
// Activate the new config to make it available
let status = try await remoteConfig.activate()
print("Config activated with status: \(status)")
}
} catch {
print("Error listening for remote config updates: \(error)")
}
}
}
This change is purely additive and does not affect any existing APIs.