gpt4 book ai didi

ios - key 更改后的 RLMException - 已使用不同的加密 key 打开

转载 作者:可可西里 更新时间:2023-11-01 03:16:37 26 4
gpt4 key购买 nike

我有一个应用程序,在注销后,出于合规性原因,需要删除所有 Realm 数据并更改加密 key 。

这与RLMException "Realm at path ' ' already opened with different encryption key" after writeCopy(toFile:,encryptionKey:)的情况不太一样。

在确保所有 Realm 对象都已解除分配后,我将删除所有文件。

+ (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)];
}

并重新创建:

+ (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];
}
}
}
}
}

但是,我经常收到 RLMException:

"reason: 'Realm at path '/Users/myname/Library/Developer/CoreSimulator/Devices/152AC3D5-FD24-40DD-AFD7-5A3C4F6EE282/data/Containers/Data/Application/2F0140CF-68E4-4D0E-8AC0-BB869BEE9BF8/Documents/default.realm' already opened with different encryption key'"

有趣的是:

'/Users/myname/Library/Developer/CoreSimulator/Devices/152AC3D5-FD24-40DD-AFD7-5A3C4F6EE282/data/Containers/Data/Application/2F0140CF-68E4-4D0E-8AC0-BB869BEE9BF8/Documents/default.realm'

甚至不在文件系统上。

有什么解决问题的提示吗?

最佳答案

就像@bdash 在他的其他问题中概述的那样,当一个 RLMRealm 实例被创建并且没有显式包含在一个 @autoreleasepool 中时,Realm 在内部缓存对该 Realm 的引用.这是设计使然,以确保 Realm 尽可能高效地运行。

虽然一个明显的解决方案是将您应用中的每个 Realm 操作简单地包含在一个 @autoreleasepool 中,但这会对性能产生不利影响,因为您将迫使 Realm 打开一个新的引用每次调用它时都会磁盘。

我有一个没有人在这里直接提到的潜在解决方案:不要回收 default.realm

这里的问题是,您正在创建 default.realm 的新副本,而内存中仍然存在对相同文件名的旧 Realm 的挥之不去的引用。

一个合理的折衷方案是,不是重新创建 default.realm,而是在每次执行此注销操作时创建一个具有唯一文件名的新 Realm 文件,然后将其设置为你的默认 Realm 。例如,生成 UUID 字符串(例如 7742e4bc-9f2b-44ae-acf1-7fb424438816.realm)而不是 default.realm,存储对其文件名的引用其他地方(NSUserDefaults 可能没问题),并将其用作 RLMRealmConfiguration 中的文件名。

这样,每当你需要删除旧的 Realm 并创建一个新的 Realm 时,新的 Realm 在你的应用程序中将被视为一个全新的实体,并且缓存的残余不会干扰,并且会随着时间的推移而消失该应用程序接下来启动。 :)

关于ios - key 更改后的 RLMException - 已使用不同的加密 key 打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45968363/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com