diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bf13e2228..5257b53759 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ x.y.z Release notes (yyyy-MM-dd) ============================================================= ### Enhancements -* None. +* Allow in-memory synced Realms. This will allow setting and in-memory identifier on + flexible sync realms, this will not create a .realm file or its associated auxiliary + files for the synced realm and instead stores objects in memory while the realm is + open and discards them immediately when all instances are closed. ### Fixed * ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?) @@ -9377,7 +9380,7 @@ Prebuilt frameworks are now built with Xcode 7.1. the properties in a `RLMObject` subclass. * Fix crash on IN query with several thousand items. * Fix crash when querying indexed `NSString` properties. -* Fixed an issue which prevented in-memory Realms from being used accross multiple threads. +* Fixed an issue which prevented in-memory Realms from being used across multiple threads. * Preserve the sort order when querying a sorted `RLMResults`. * Fixed an issue with migrations where if a Realm file is deleted after a Realm is initialized, the newly created Realm can be initialized with an incorrect schema version. diff --git a/Realm/ObjectServerTests/AsyncSyncTests.swift b/Realm/ObjectServerTests/AsyncSyncTests.swift index 64b6d734bc..923e05655f 100644 --- a/Realm/ObjectServerTests/AsyncSyncTests.swift +++ b/Realm/ObjectServerTests/AsyncSyncTests.swift @@ -514,6 +514,52 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase { checkCount(expected: 10, realm, SwiftPerson.self) } + @MainActor + func testFlexibleSyncInitInMemory() async throws { + try await populateSwiftPerson(5) + + let user = try await createUser() + try await Task { + var config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in + subs.append(QuerySubscription { + $0.age > 0 && $0.firstName == "\(#function)" + }) + }) + config.objectTypes = [SwiftPerson.self] + config.inMemoryIdentifier = "identifier" + let inMemoryRealm = try await Realm(configuration: config, downloadBeforeOpen: .always) + XCTAssertEqual(inMemoryRealm.objects(SwiftPerson.self).count, 5) + try! inMemoryRealm.write { + let person = SwiftPerson(firstName: "\(#function)", + lastName: "lastname_10", + age: 10) + inMemoryRealm.add(person) + } + XCTAssertEqual(inMemoryRealm.objects(SwiftPerson.self).count, 6) + try await inMemoryRealm.syncSession?.wait(for: .upload) + }.value + + var config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in + subs.append(QuerySubscription { + $0.age > 5 && $0.firstName == "\(#function)" + }) + }) + config.objectTypes = [SwiftPerson.self] + config.inMemoryIdentifier = "identifier" + let inMemoryRealm = try await Realm(configuration: config, downloadBeforeOpen: .always) + XCTAssertEqual(inMemoryRealm.objects(SwiftPerson.self).count, 1) + + var config2 = user.flexibleSyncConfiguration(initialSubscriptions: { subs in + subs.append(QuerySubscription { + $0.age > 0 && $0.firstName == "\(#function)" + }) + }) + config2.objectTypes = [SwiftPerson.self] + config2.inMemoryIdentifier = "identifier2" + let inMemoryRealm2 = try await Realm(configuration: config2, downloadBeforeOpen: .always) + XCTAssertEqual(inMemoryRealm2.objects(SwiftPerson.self).count, 6) + } + @MainActor func testStates() async throws { let realm = try await openRealm() diff --git a/Realm/RLMRealmConfiguration.h b/Realm/RLMRealmConfiguration.h index d09e5c215b..2768a0d590 100644 --- a/Realm/RLMRealmConfiguration.h +++ b/Realm/RLMRealmConfiguration.h @@ -75,13 +75,13 @@ typedef void(^RLMFlexibleSyncInitialSubscriptionsBlock)(RLMSyncSubscriptionSet * #pragma mark - Properties -/// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier`; +/// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier`, /// setting one of the two properties will automatically nil out the other. @property (nonatomic, copy, nullable) NSURL *fileURL; /// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL`, -/// `seedFilePath`and `syncConfiguration`; -/// setting any one of the three properties will automatically nil out the other two. +/// `seedFilePath`. +/// setting an in-memory identifier will automatically nil out the other two. @property (nonatomic, copy, nullable) NSString *inMemoryIdentifier; /// A 64-byte key to use to encrypt the data, or `nil` if encryption is not enabled. diff --git a/Realm/RLMRealmConfiguration.mm b/Realm/RLMRealmConfiguration.mm index 692922b550..bfeeadace7 100644 --- a/Realm/RLMRealmConfiguration.mm +++ b/Realm/RLMRealmConfiguration.mm @@ -174,7 +174,6 @@ - (void)setInMemoryIdentifier:(NSString *)inMemoryIdentifier { if (inMemoryIdentifier.length == 0) { @throw RLMException(@"In-memory identifier must not be empty"); } - _config.sync_config = nullptr; _seedFilePath = nil; RLMNSStringToStdString(_config.path, [NSTemporaryDirectory() stringByAppendingPathComponent:inMemoryIdentifier]); @@ -367,7 +366,6 @@ - (void)setSyncConfiguration:(RLMSyncConfiguration *)syncConfiguration { } NSAssert(user.identifier, @"Cannot call this method on a user that doesn't have an identifier."); - _config.in_memory = false; _config.sync_config = std::make_shared(syncConfiguration.rawConfiguration); _config.path = syncConfiguration.path; diff --git a/RealmSwift/RealmConfiguration.swift b/RealmSwift/RealmConfiguration.swift index fdec05b357..193c37e421 100644 --- a/RealmSwift/RealmConfiguration.swift +++ b/RealmSwift/RealmConfiguration.swift @@ -51,8 +51,9 @@ extension Realm { /** Creates a `Configuration` which can be used to create new `Realm` instances. - - note: The `fileURL`, `inMemoryIdentifier`, and `syncConfiguration` parameters are mutually exclusive. Only + - note: The `fileURL`, `inMemoryIdentifier`, parameters are mutually exclusive. Only set one of them, or none if you wish to use the default file URL. + Synced Realms will set a unique file path unless is an in-memory realm. - parameter fileURL: The local URL to the Realm file. - parameter inMemoryIdentifier: A string used to identify a particular in-memory Realm. @@ -106,15 +107,13 @@ extension Realm { // MARK: Configuration Properties /** - A configuration value used to configure a Realm for synchronization with Atlas App Services. Mutually - exclusive with `inMemoryIdentifier`. + A configuration value used to configure a Realm for synchronization with Atlas App Services. */ public var syncConfiguration: SyncConfiguration? { get { return _syncConfiguration } set { - _inMemoryIdentifier = nil _syncConfiguration = newValue } } @@ -128,15 +127,13 @@ extension Realm { } } - /// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL` and - /// `syncConfiguration`. + /// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL`. public var inMemoryIdentifier: String? { get { return _inMemoryIdentifier } set { fileURL = nil - _syncConfiguration = nil _inMemoryIdentifier = newValue } }