diff --git a/CHANGELOG.md b/CHANGELOG.md index 06969a4ab0..ec951ebbd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,14 @@ x.y.z Release notes (yyyy-MM-dd) ============================================================= ### Enhancements -* Redesign `@AsyncOpen` and `@AutoOpen` initialisers to allow setting a client reset modes for any sync configuration, - and avoid confusion with the injected configuration and the sync configuration from the user on each intialiser. +* Fix `@AsyncOpen` and `@AutoOpen` not using the syncConfiguration passed through + the `configuration`, this is not allowing for the `initialSubscription` and + `clientResetMode` to be passed in the initialiser or as an environment value. ### Fixed * ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?) * None. -### Breaking Changes -* `AsyncOpen.init(appId:partitionValue:configuration:timeout)` and - `AutoOpen.init(appId:partitionValue:configuration:timeout)` will change behavior. Previously - injecting both the configuration and a partition value will make the property wrappers to set - the injected configuration (if not nil) combine with the syncConfiguration from the - `user.configuration(partitionValue:)`. This will change to either user the injected configuration (if not nil) - or the configuration obtained from `user.configuration(partitionValue:)` for the current logged user. - This API will be deprecated on the next major release. -* `AsyncOpen.init(appId:configuration:timeout)` and `AutoOpen.init(appId:configuration:timeout)` - will change behavior. Previously this initialiser will set the injected configuration (if present) - combine with the flexible sync configuration `user.flexibleSyncConfiguration` from the logged user. - This will change to use the injected configuration which should already include a sync configuration. -* `AsyncOpen.init(appId:partitionValue:timeout)` and `AutoOpen.init(appId:partitionValue:timeout)` - are two new initialisers which allow us to configure the property wrappers for a partition based sync - configuration for the current logged user. -* `AsyncOpen.init(appId:timeout)` and `AutoOpen.init(appId:timeout)` are two new initialisers which - allow us to configure the property wrappers for a flexible sync configuration for the current logged user. - ### Compatibility * Realm Studio: 14.0.1 or later. * APIs are backwards compatible with all previous releases in the 10.x.y series. diff --git a/Realm/ObjectServerTests/SwiftUIServerTests.swift b/Realm/ObjectServerTests/SwiftUIServerTests.swift index b701b10f6a..667eeb4aee 100644 --- a/Realm/ObjectServerTests/SwiftUIServerTests.swift +++ b/Realm/ObjectServerTests/SwiftUIServerTests.swift @@ -348,7 +348,7 @@ class SwiftUIServerTests: SwiftSyncTestCase { func testAsyncOpenPBSWithConfiguration() throws { let user = try logInUser(for: basicCredentials()) if !isParent { - populateRealm(user: user, partitionValue: #function) + try populateRealm(user: user, partitionValue: #function) return } executeChild() @@ -809,7 +809,7 @@ class SwiftUIServerTests: SwiftSyncTestCase { func testAutoOpenPBSWithConfiguration() throws { let user = try logInUser(for: basicCredentials()) if !isParent { - populateRealm(user: user, partitionValue: #function) + try populateRealm(user: user, partitionValue: #function) return } executeChild() diff --git a/RealmSwift/SwiftUI.swift b/RealmSwift/SwiftUI.swift index 9864bfdc64..14ae403844 100644 --- a/RealmSwift/SwiftUI.swift +++ b/RealmSwift/SwiftUI.swift @@ -1526,15 +1526,25 @@ private class ObservableAsyncOpenStorage: ObservableObject { } private func asyncOpenForUser(_ user: User) { - // Set the `syncConfiguration` depending if there is partition value (pbs) or not (flx). var config: Realm.Configuration - if let configuration = configuration { - // We want to throw if the configuration doesn't contain a `SyncConfiguration` - guard configuration.syncConfiguration != nil else { - throwRealmException("The used configuration was not configured with sync.") - } + if let configuration = self.configuration { config = configuration + var syncConfig: SyncConfiguration? + if let syncConfiguration = configuration.syncConfiguration { + if let partitionValue = partitionValue { + syncConfig = user.configuration(partitionValue: partitionValue, clientResetMode: syncConfiguration.clientResetMode).syncConfiguration + } + } else { + if let partitionValue = partitionValue { + syncConfig = user.configuration(partitionValue: partitionValue).syncConfiguration + } else { + syncConfig = user.flexibleSyncConfiguration().syncConfiguration + } + } + if let syncConfig = syncConfig { + config.syncConfiguration = syncConfig + } } else { if let partitionValue = partitionValue { config = user.configuration(partitionValue: partitionValue) @@ -1542,6 +1552,7 @@ private class ObservableAsyncOpenStorage: ObservableObject { config = user.flexibleSyncConfiguration() } } + let syncConfiguration = config.syncConfiguration syncConfiguration?.config.cancelAsyncOpenOnNonFatalErrors = true config.syncConfiguration = syncConfiguration @@ -1586,7 +1597,7 @@ private class ObservableAsyncOpenStorage: ObservableObject { } // We don't want to use the `defaultConfiguration` from the environment, we only want to use this environment value in @AsyncOpen if is not the default one - if configuration != .defaultConfiguration, self.configuration != configuration { + if configuration == .defaultConfiguration, self.configuration != configuration { if let partitionValue = configuration.syncConfiguration?.partitionValue { self.partitionValue = partitionValue } @@ -1705,9 +1716,9 @@ private class ObservableAsyncOpenStorage: ObservableObject { - parameter timeout: The maximum number of milliseconds to allow for a connection to become fully established., if empty or `nil` no connection timeout is set. - - note: This intialiser will use either the configuration or build a configuration from the partition value using `user.configuration(partitionValue:)`. + - note: This intializer will use either the configuration (if not nil) with the given partition value, or build a configuration from the + partition value using `user.configuration(partitionValue:)`. */ - @available(*, deprecated, message: "This API will be deprecated. Use init(appId:partitionValue:timeout) if you want are connecting to a partition based sync without a configuration, or init(appId:configuration:timeout) in case you are using a configuration") public init(appId: String? = nil, partitionValue: Partition, configuration: Realm.Configuration? = nil, @@ -1718,11 +1729,14 @@ private class ObservableAsyncOpenStorage: ObservableObject { } /** - Initialize the property wrapper with a configuration. + Initialize the property wrapper for a flexible sync app. - parameter appId: The unique identifier of your Realm app, if empty or `nil` will try to retrieve latest singular cached app. - parameter configuration: A configuration `Realm.configuration` to use when opening the Realm. - parameter timeout: The maximum number of milliseconds to allow for a connection to become fully established., if empty or `nil` no connection timeout is set. + + - note: This intializer will use either the configuration (if not nil), or build a configuration from the + partition value using `user.flexibleSyncConfiguration()`. */ public init(appId: String? = nil, configuration: Realm.Configuration? = nil, @@ -1732,34 +1746,6 @@ private class ObservableAsyncOpenStorage: ObservableObject { storage = ObservableAsyncOpenStorage(asyncOpenKind: .asyncOpen, app: app, configuration: configuration, partitionValue: nil) } - /** - Initialize the property wrapper for a partition sync based sync app. - - parameter appId: The unique identifier of your Realm app, if empty or `nil` will try to retrieve latest singular cached app. - - parameter partitionValue: The `BSON` value the Realm is partitioned on. - - parameter timeout: The maximum number of milliseconds to allow for a connection to - become fully established., if empty or `nil` no connection timeout is set. - */ - public init(appId: String? = nil, - partitionValue: Partition, - timeout: UInt? = nil) where Partition: BSON { - let app = ObservableAsyncOpenStorage.configureApp(appId: appId, timeout: timeout) - // Store property wrapper values on the storage - storage = ObservableAsyncOpenStorage(asyncOpenKind: .asyncOpen, app: app, configuration: nil, partitionValue: AnyBSON(partitionValue)) - } - - /** - Initialize the property wrapper for a flexible sync app. - - parameter appId: The unique identifier of your Realm app, if empty or `nil` will try to retrieve latest singular cached app. - - parameter timeout: The maximum number of milliseconds to allow for a connection to - become fully established., if empty or `nil` no connection timeout is set. - */ - public init(appId: String? = nil, - timeout: UInt? = nil) { - let app = ObservableAsyncOpenStorage.configureApp(appId: appId, timeout: timeout) - // Store property wrapper values on the storage - storage = ObservableAsyncOpenStorage(asyncOpenKind: .asyncOpen, app: app, configuration: nil, partitionValue: nil) - } - nonisolated public func update() { assumeOnMainActorExecutor { storage.update(partitionValue, configuration) @@ -1846,7 +1832,6 @@ private class ObservableAsyncOpenStorage: ObservableObject { - note: This intialiser will use either the configuration or build a configuration from the partition value using `user.configuration(partitionValue:)`. */ - @available(*, deprecated, message: "This API will be deprecated. Use init(appId:partitionValue:timeout) if you want are connecting to a partition based sync without a configuration, or init(appId:configuration:timeout) in case you are using a configuration") public init(appId: String? = nil, partitionValue: Partition, configuration: Realm.Configuration? = nil, @@ -1871,35 +1856,6 @@ private class ObservableAsyncOpenStorage: ObservableObject { storage = ObservableAsyncOpenStorage(asyncOpenKind: .autoOpen, app: app, configuration: configuration, partitionValue: nil) } - /** - Initialize the property wrapper for a partition sync based sync app. - - parameter appId: The unique identifier of your Realm app, if empty or `nil` will try to retrieve latest singular cached app. - - parameter partitionValue: The `BSON` value the Realm is partitioned on. - - parameter timeout: The maximum number of milliseconds to allow for a connection to - become fully established., if empty or `nil` no connection timeout is set. - */ - public init(appId: String? = nil, - partitionValue: Partition, - timeout: UInt? = nil) where Partition: BSON { - let app = ObservableAsyncOpenStorage.configureApp(appId: appId, timeout: timeout) - // Store property wrapper values on the storage - storage = ObservableAsyncOpenStorage(asyncOpenKind: .autoOpen, app: app, configuration: nil, partitionValue: AnyBSON(partitionValue)) - } - - /** - Initialize the property wrapper for a flexible sync app. - - parameter appId: The unique identifier of your Realm app, if empty or `nil` will try to retrieve latest singular cached app. - - parameter timeout: The maximum number of milliseconds to allow for a connection to - become fully established., if empty or `nil` no connection timeout is set. - */ - public init(appId: String? = nil, - timeout: UInt? = nil) { - let app = ObservableAsyncOpenStorage.configureApp(appId: appId, timeout: timeout) - // Store property wrapper values on the storage - storage = ObservableAsyncOpenStorage(asyncOpenKind: .autoOpen, app: app, configuration: nil, partitionValue: nil) - } - - nonisolated public func update() { assumeOnMainActorExecutor { storage.update(partitionValue, configuration)