RLMException after changing the key - already open with a different encryption key in the feed

I have an application that, after logging out for compliance reasons, should erase all Realm data and change the encryption key.

This is not exactly the same RLMException "Realm at path '' already opened with a different encryption key" after writeCopy (toFile :, encryptionKey :)

I delete all files after all Realm objects have been freed.

+ (void)deleteRealm:(BOOL)emptyDatabase numRetries:(NSUInteger)numRetries { [[NSNotificationCenter defaultCenter] postNotificationName:@"AppDataStoreWillFlushDatabaseNotification" object:self]; if (emptyDatabase) { @autoreleasepool { RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm deleteAllObjects]; }]; [realm invalidate]; } } NSFileManager *manager = [NSFileManager defaultManager]; RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; NSArray<NSURL *> *realmFileURLs = @[ config.fileURL, [config.fileURL URLByAppendingPathExtension:@"lock"], [config.fileURL URLByAppendingPathExtension:@"log_a"], [config.fileURL URLByAppendingPathExtension:@"log_b"], [config.fileURL URLByAppendingPathExtension:@"note"], [[config.fileURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.realm.management", [[config.fileURL URLByDeletingPathExtension] lastPathComponent]]] ]; for (NSURL *URL in realmFileURLs) { NSError *error = nil; [manager removeItemAtURL:URL error:&error]; if (error) { // handle error DDLogError(@"Error deleting realm file - %@", error); } } // Remove old password [CHPasswordManager wipeKeyFromSecurityEnclave]; [self configureRealm:(numRetries + 1)]; } 

And recreation with:

 + (void)configureRealm:(NSUInteger)numRetries { // Setup the encryption key NSString *encryptionKey = [CHPasswordManager encryptedStorePassphrase]; // If encryption key is not valid anymore, generate a new one (CoreData used a 32 chars string while Realm uses a 64 chars string) if (encryptionKey.length == 32) { [CHPasswordManager wipeKeyFromSecurityEnclave]; encryptionKey = [CHPasswordManager encryptedStorePassphrase]; } NSData *key = [encryptionKey dataUsingEncoding:NSUTF8StringEncoding]; RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; config.encryptionKey = key; // Set this as the configuration used for the default Realm [RLMRealmConfiguration setDefaultConfiguration:config]; @autoreleasepool { @try { [RealmUser allObjects]; }@catch (NSException *e) { if ([e.name isEqual:@"RLMException"]) { // Something went wrong with encryption key - delete database and recreate again if (numRetries >= kRetriesThreshold) { [Bugsnag notify:e]; } else { [self deleteRealm:NO numRetries:numRetries]; } } } } } 

However, I often get an RLMException:

"reason: 'Kingdom on the way' / Users / myname / Library / Developer / CoreSimulator / Devices / 152AC3D5-FD24-40DD-AFD7-5A3C4F6EE282 / data / Containers / Data / Application / 2F0140CF-68E4-4D0E-8AC0-BB869BEE9BF8 / Documents /default.realm 'is already open with a different encryption key "

It’s funny that:

'/Users/MyName/Library/Developer/CoreSimulator/Devices/152AC3D5-FD24-40DD-AFD7-5A3C4F6EE282/data/Containers/Data/Application/2F0140CF-68E4-4D0E-8AC0-BB869.Deme

Not even in the file system.

Any hints to fix the problem?

+7
ios objective-c realm
source share
1 answer

Like @bdash described in another of his RLMRealm , when an RLMRealm instance RLMRealm created and not explicitly contained in @autoreleasepool , Realm internally caches links to this area. This is done specifically for Realm to work as efficiently as possible.

Although the obvious solution would be to simply @autoreleasepool literally every Realm operation in your application in @autoreleasepool , this is negatively @autoreleasepool for performance, because then you will force Realm to open a new disk link every time you invoke it.

I have one potential solution that no one directly mentioned here: do not restart default.realm .

The problem here is that you are creating a new copy of default.realm while links to the old area with the same file name are still stored in memory.

A reasonable compromise would be that instead of re- default.realm you instead create a new Realm file with a unique file name each time you perform this logout operation and then set it as the default area. For example, instead of default.realm you generate a UUID string (for example, 7742e4bc-9f2b-44ae-acf1-7fb424438816.realm ), keep a link to its file name somewhere else ( NSUserDefaults , probably good) and use it as the file name in RLMRealmConfiguration .

Thus, whenever you need to delete the old Kingdom and create a new one, the new one will be considered a completely new entity in your application, and the rest of the cache will not interfere and disappear by the time the application launches next. :)

+1
source share

All Articles