diff --git a/Realm/RLMCollection.mm b/Realm/RLMCollection.mm index 416a82f808..380a9d1484 100644 --- a/Realm/RLMCollection.mm +++ b/Realm/RLMCollection.mm @@ -527,7 +527,7 @@ - (bool)invalidate { } RLMThreadSafeReference *tsr = [RLMThreadSafeReference referenceWithThreadConfined:collection]; - RLMRealmConfiguration *config = realm.configuration; + RLMRealmConfiguration *config = realm.configurationSharingSchema; dispatch_async(queue, ^{ std::lock_guard lock(token->_mutex); if (!token->_realm) { diff --git a/Realm/RLMObjectBase.mm b/Realm/RLMObjectBase.mm index a31310fe43..0cc1b5a114 100644 --- a/Realm/RLMObjectBase.mm +++ b/Realm/RLMObjectBase.mm @@ -790,7 +790,7 @@ - (void)registrationComplete:(void (^)())completion { RLMThreadSafeReference *tsr = [RLMThreadSafeReference referenceWithThreadConfined:(id)obj]; auto token = [[RLMObjectNotificationToken alloc] init]; token->_realm = obj->_realm; - RLMRealmConfiguration *config = obj->_realm.configuration; + RLMRealmConfiguration *config = obj->_realm.configurationSharingSchema; dispatch_async(queue, ^{ @autoreleasepool { [token addNotificationBlock:block threadSafeReference:tsr config:config keyPaths:keyPaths queue:queue]; diff --git a/Realm/RLMRealm.mm b/Realm/RLMRealm.mm index c5e177eb2c..316ff4f58d 100644 --- a/Realm/RLMRealm.mm +++ b/Realm/RLMRealm.mm @@ -596,6 +596,14 @@ - (RLMRealmConfiguration *)configuration { return configuration; } +- (RLMRealmConfiguration *)configurationSharingSchema { + RLMRealmConfiguration *configuration = [[RLMRealmConfiguration alloc] init]; + configuration.configRef = _realm->config(); + configuration.dynamic = _dynamic; + [configuration setCustomSchemaWithoutCopying:_schema]; + return configuration; +} + - (void)beginWriteTransaction { [self beginWriteTransactionWithError:nil]; } @@ -1076,7 +1084,7 @@ - (RLMRealm *)freeze { - (RLMRealm *)thaw { [self verifyThread]; - return self.isFrozen ? [RLMRealm realmWithConfiguration:self.configuration error:nil] : self; + return self.isFrozen ? [RLMRealm realmWithConfiguration:self.configurationSharingSchema error:nil] : self; } - (RLMRealm *)frozenCopy { diff --git a/Realm/RLMRealmUtil.mm b/Realm/RLMRealmUtil.mm index 2fad212f6e..ceb87fb967 100644 --- a/Realm/RLMRealmUtil.mm +++ b/Realm/RLMRealmUtil.mm @@ -234,7 +234,7 @@ @implementation RLMPinnedRealm { - (instancetype)initWithRealm:(RLMRealm *)realm { if (self = [super init]) { _pin = realm->_realm->duplicate(); - _configuration = realm.configuration; + _configuration = realm.configurationSharingSchema; } return self; } diff --git a/Realm/RLMRealm_Private.h b/Realm/RLMRealm_Private.h index d247de39bc..e2bfa264fc 100644 --- a/Realm/RLMRealm_Private.h +++ b/Realm/RLMRealm_Private.h @@ -65,6 +65,11 @@ FOUNDATION_EXTERN void RLMRealmSubscribeToAll(RLMRealm *); @property (nonatomic, readonly, nullable) id actor; @property (nonatomic, readonly) bool isFlexibleSync; +// `-configuration` does a deep copy of the schema as if the user mutates the +// RLMSchema in use by a RLMRealm things will break horribly. When we know that +// the configuration won't be exposed we can skip the copy. +- (RLMRealmConfiguration *)configurationSharingSchema NS_RETURNS_RETAINED; + + (void)resetRealmState; - (void)registerEnumerator:(RLMFastEnumerator *)enumerator; diff --git a/Realm/RLMResults.mm b/Realm/RLMResults.mm index 699eac7bf8..eac9566e7b 100644 --- a/Realm/RLMResults.mm +++ b/Realm/RLMResults.mm @@ -574,7 +574,7 @@ - (void)completionWithThreadSafeReference:(RLMThreadSafeReference * _Nullable)re confinedTo:(RLMScheduler *)confinement completion:(RLMResultsCompletionBlock)completion error:(NSError *_Nullable)error { - RLMRealmConfiguration *configuration = _realm.configuration; + RLMRealmConfiguration *configuration = _realm.configurationSharingSchema; [confinement invoke:^{ if (error) { return completion(nil, error); diff --git a/RealmSwift/Combine.swift b/RealmSwift/Combine.swift index a55a5ee77c..4049597d45 100644 --- a/RealmSwift/Combine.swift +++ b/RealmSwift/Combine.swift @@ -939,7 +939,7 @@ public enum RealmPublishers { try? Realm(RLMRealm(configuration: config, queue: scheduler as? DispatchQueue)) } static private func realm(_ sourceRealm: Realm, _ scheduler: S) -> Realm? { - return realm(sourceRealm.rlmRealm.configuration, scheduler) + return realm(sourceRealm.rlmRealm.configurationSharingSchema(), scheduler) } /// A publisher which emits an asynchronously opened Realm. @@ -1300,7 +1300,7 @@ public enum RealmPublishers { private let scheduler: S internal init(_ upstream: Upstream, _ scheduler: S, _ realm: Realm) { - self.config = realm.rlmRealm.configuration + self.config = realm.rlmRealm.configurationSharingSchema() self.upstream = upstream self.scheduler = scheduler } @@ -1377,7 +1377,7 @@ public enum RealmPublishers { self.upstream .map { (obj: Output) -> Handover in guard let realm = obj.realm, !realm.isFrozen else { return .object(obj) } - return .tsr(ThreadSafeReference(to: obj), config: realm.rlmRealm.configuration) + return .tsr(ThreadSafeReference(to: obj), config: realm.rlmRealm.configurationSharingSchema()) } .receive(on: scheduler) .compactMap { (handover: Handover) -> Output? in diff --git a/RealmSwift/Impl/RealmCollectionImpl.swift b/RealmSwift/Impl/RealmCollectionImpl.swift index 69d31af1a1..3249e1e38c 100644 --- a/RealmSwift/Impl/RealmCollectionImpl.swift +++ b/RealmSwift/Impl/RealmCollectionImpl.swift @@ -195,7 +195,7 @@ internal func with( } let tsr = ThreadSafeReference(to: value) - let config = Unchecked(wrappedValue: value.realm!.rlmRealm.configuration) + let config = Unchecked(wrappedValue: value.realm!.rlmRealm.configurationSharingSchema()) return try await actor.invoke { actor in if Task.isCancelled { return nil