0

REALM バージョン 0.98.1 (Objective C 用) を使用していますが、アプリの起動時にDB サイズを圧縮しているときに、「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 へのコードです (DB サイズを圧縮します):

+ (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 」メソッドで適切に構成されていることを確認しました(参照用に添付のスクリーン ショットを参照)

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 に答える