0

我使用的是 REALM 版本 0.98.1(对于 Objective C),有时在应用启动时压缩数据库大小时会出现“ Bad Realm file header ”异常。

下面是 AppDelegate 应用程序 didFinishLaunch 中的方法调用序列......

[self setDefaultConfigrutaionForRealm];
[self vacuumRealm];

下面是配置领域的代码:

+(void)setDefaultConfigrutaionForRealm{
    RLMRealmConfiguration * defCongfig = [RLMRealmConfiguration defaultConfiguration];
    defCongfig.path = REALM_PATH(REALM_FILE_NAME);
    defCongfig.schemaVersion = SCHEMA_VERSION; 
    [RLMRealmConfiguration setDefaultConfiguration:defCongfig];
}

以下是 VacuumRealm 的代码(压缩数据库大小):

+ (void)vacuumRealm {
@try{
    @autoreleasepool {
        RLMRealm *realm = [RLMRealm defaultRealm];
        NSString *realmPath = [realm path];
        NSLog(@"vacuumRealm realmPath = %@", realmPath);

        long long fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:realmPath error:nil][NSFileSize] longLongValue];
        NSLog(@"vacuumRealm ENTER filesize = %llu", fileSize);

        //
        NSError *err;
        BOOL success;
        NSDate *startDate = [NSDate date];
        NSString *copyPath = [realmPath stringByAppendingString:@".copy"];

        [[NSFileManager defaultManager] removeItemAtPath:copyPath error:&err];
        success = [realm writeCopyToPath:copyPath error:&err];

        if (success) {
            success = [[NSFileManager defaultManager] removeItemAtPath:realmPath error:&err];
            if (success) {
                success = [[NSFileManager defaultManager] copyItemAtPath:copyPath toPath:realmPath error:&err];
                if (success) {
                    [[NSFileManager defaultManager] removeItemAtPath:copyPath error:&err];

                    NSDate *endDate = [NSDate date];
                    NSTimeInterval executionTime = [endDate timeIntervalSinceDate:startDate];
                    NSLog(@"vacuumRealm cleanup took %f ms", executionTime);
                }
            }
        }
        //

        fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:realmPath error:nil][NSFileSize] longLongValue];
        NSLog(@"vacuumRealm EXIT filesize = %llu", fileSize);
    }
}
@catch (NSException *exception) {
    NSLog(@"Inside vacuumRealm exception = %@",exception.description);
}
@finally {
  }
 }

在调试时,我观察到领域路径已在“ setDefaultConfigrutaionForRealm ”方法中正确配置(附加屏幕截图供参考),但一旦在那里调用“ vacuumRealm ”方法,我会在下面的行中得到“ Bad Realm file header (#1) ”:

RLMRealm *realm = [RLMRealm defaultRealm];

屏幕截图显示 - 在 setDefaultConfigrutaionForRealm 方法领域数据库路径已正确设置。

解决此异常的任何帮助都将非常有帮助。

提前致谢。

4

1 回答 1

1

您正在创建一个 Realm 实例 ( RLMRealm *realm = [RLMRealm defaultRealm];) 并从它下面删除文件而不释放实例。这将导致您看到的损坏等问题,因为您正在修改文件,而 Realm 仍在访问它。

这是您的方法的更新版本(省略调试日志,err因为它没有被使用):

__block BOOL copySuccess = NO;
NSString *realmPath = [[RLMRealmConfiguration defaultConfiguration] path];
NSString *copyPath = [realmPath stringByAppendingString:@".copy"];
@autoreleasepool {
    [[NSFileManager defaultManager] removeItemAtPath:copyPath error:nil];
    copySuccess = [[RLMRealm defaultRealm] writeCopyToPath:copyPath error:nil];
}
if (copySuccess && [[NSFileManager defaultManager] removeItemAtPath:realmPath error:nil]) {
    [[NSFileManager defaultManager] moveItemAtPath:copyPath toPath:realmPath error:nil];
}

此外,在此过程中抛出的任何异常都不是可恢复的。所以在块中唯一安全的事情@catch就是中止。或者根本没有@try/@catch子句。

于 2016-02-19T18:21:06.330 回答