ios - RLMException "Realm at path ' ' already opened with different encryption key" after writeCopy(toFile:,encryptionKey:) -



i'm trying change encryption key realm database using writecopy(tofile:, encryptionkey:), below:

public static func updateencryption(fornewkey newkey: string, witholdkey oldkey: string, completion: (() -> void)) {      let defaulturl = backup.realmcontainerurl     let defaultparenturl = defaulturl.deletinglastpathcomponent()     let compactedurl = defaultparenturl.appendingpathcomponent("default-compact.realm")      let oldkeydata = oldkey.pbkdf2sha256(keybytecount: 64)     let newkeydata = newkey.pbkdf2sha256(keybytecount: 64)      let oldencryptionconfig = realm.configuration(fileurl: backup.realmcontainerurl, encryptionkey: oldkeydata)      autoreleasepool {         {             let oldrealm = try realm(configuration: oldencryptionconfig)             try oldrealm.writecopy(tofile: compactedurl, encryptionkey: newkeydata)             oldrealm.invalidate()             try filemanager.default.removeitem(at: defaulturl)             try filemanager.default.moveitem(at: compactedurl, to: defaulturl)             completion()         } catch {             fatalerror(error.localizeddescription)         }     } } 

after that, i'm reloading data in app using:

public static func loadall(withencryptionkey encryptionkey: string) -> [backup] {     {         let key = encryptionkey.pbkdf2sha256(keybytecount: 64)         let encryptionconfig = realm.configuration(fileurl: backup.realmcontainerurl, encryptionkey: key)         let realm = try realm(configuration: encryptionconfig)         let allobjects = realm.objects(backup.self).sorted(bykeypath: "date", ascending: false)         return allobjects.map({ $0 })     } catch {         fatalerror(error.localizeddescription)     } } 

so use loadall(withencryptionkey:) function new key, on let realm = try realm(configuration: encryptionconfig) app crashes in rlmrealm.mm file, line 347: @throw rlmexception(@"realm @ path '%s' opened different encryption key", config.path.c_str()); console log libc++abi.dylib: terminating uncaught exception of type nsexception.
looks writecopy(tofile:, encryptionkey:) did not change encryptionkey, or realm still sees old .realm file. what's funny, after reopening app, loadall(withencryptionkey:) loads data new encryption key without problems.
how solve problem? how change encryption key , still able use app?
grateful help.

it depends on call loadall() method. perhaps calling in completion(), right? if so, @ point reference old realm has not yet been released , remains open.

much deleting/replacing realm file disk, it's safe replace realm file on disk if application not have realm file open.

from realm's documentation on deleting realm files:

because realm avoids copying data memory except when absolutely required, objects managed realm contain references file on disk, , must deallocated before file can safely deleted. includes objects read (or added to) realm, list, results, , threadsafereference objects, , realm itself.

in practice, means deleting realm file should done either on application startup before have opened realm, or after opening realm within explicit autorelease pool, ensures of realm objects have been deallocated.

the reason realm maintains in-memory cache of open files, attempting open file that's open result in reference already-open file being returned. open file continue refer original file on disk, if has since been replaced. ensuring references realm accessor objects have been cleaned means realm not have existing open file return, , instead open file disk.

in other words, must make sure have no references realm's accessor objects (realm, results, threadsafereference or object instances) @ point when attempt replace realm file. must make sure references did have have since been deallocated.

if there no other references realm , realm objects @ point, succeed opening outside autorelease block, following.

autoreleasepool {     {         let oldrealm = try realm(configuration: oldencryptionconfig)         try oldrealm.writecopy(tofile: compactedurl, encryptionkey: newkeydata)         oldrealm.invalidate()         try filemanager.default.removeitem(at: defaulturl)         try filemanager.default.moveitem(at: compactedurl, to: defaulturl)     } catch {         fatalerror(error.localizeddescription)     } }  loadall(withencryptionkey: ...) 

an alternative approach may easier manage use different path when attempt reopen restored file. since you're accessing different path on disk you'll guaranteed open new file. you'll still need make sure have no references realm's accessor objects since otherwise you'll weird mix of old , new data, won't critical ensure accessor objects deallocated.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -