我有一个应用程序,在注销后,出于合规性原因,需要擦除所有Realm数据并更改加密密钥。
的情况并不完全相同我确保在释放所有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:
“理由:'道路上的境界 '/Users/myname/Library/Developer/CoreSimulator/Devices/152AC3D5-FD24-40DD-AFD7-5A3C4F6EE282/data/Containers/Data/Application/2F0140CF-68E4-4D0E-8AC0-BB869BEE9BF8/Documents/default.realm' 已经使用不同的加密密钥'“
打开
有趣的是:
“/用户/ MYNAME /库/开发商/ CoreSimulator /设备/ 152AC3D5-FD24-40DD-AFD7-5A3C4F6EE282 /数据/容器/数据/应用/ 2F0140CF-68E4-4D0E-8AC0-BB869BEE9BF8 /文档/ default.realm “
甚至不在文件系统上。
解决问题的任何提示?
答案 0 :(得分:2)
就像他的另一个问题中概述的@bdash一样,当创建<ion-item [color]="colorCondition(item) ? 'primary' : 'light'">
//in your ts file
colorCondition(item : ItemSliding){
let initItem = this.incompleteOrders.indexOf(item);
let orderStatus = this.incompleteOrders[initItem].status;
if(orderStatus == 'paid'){
return false;
}else if(orderStatus == 'pending'){
return true;
}
}
实例且未明确包含在RLMRealm
中时,Realm在内部缓存对该Realm的引用。这是设计使然,以确保Realm尽可能高效地运行。
虽然显而易见的解决方案是将应用程序中的每个Realm操作简单地括在@autoreleasepool
中,但这将对性能造成不利影响,因为您将随后迫使Realm打开每个磁盘的新引用,并每次调用它。
我有一个可能的解决方案,在这里没有人直接提及:不要回收@autoreleasepool
。
这里的问题是,您正在创建default.realm
的新副本,而在内存中仍然有对相同文件名的旧域的持久引用。
一个合理的折衷方法是,您每次执行注销操作时,都使用一个唯一的文件名创建一个新的Realm文件,而不是重新创建default.realm
,然后将其设置为默认Realm。例如,您生成一个UUID字符串(例如default.realm
)而不是default.realm
,将对其文件名的引用存储在其他位置(7742e4bc-9f2b-44ae-acf1-7fb424438816.realm
可能没问题),然后将其用作NSUserDefaults
中的文件名。
这样,每当您需要删除旧的Realm并创建一个新的Realm时,新的Realm就会在您的应用中被视为一个全新的实体,并且缓存的剩余部分不会受到干扰,并且到那时就会消失该应用程序下次启动。 :)