Заголовок файла Bad Realm (#1) Исключение при открытии файла Realm в iOS

Я использую REALM версии 0.98.1 (для цели C) и иногда получаю исключение "Bad Realm file header" при сжатии размера БД на запуск приложения.

Ниже приведена последовательность вызова метода в приложении AppDelegate didFinishLaunch....

[self setDefaultConfigrutaionForRealm];
[self vacuumRealm];

Ниже приведен код для настройки Realm:

+(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 (#1)" в строке ниже:

RLMRealm *realm = [RLMRealm defaultRealm];

скриншот показывает - в методе setDefaultConfigrutaionForRealm правильно установлен путь к базе данных области.

любая помощь в устранении этого исключения будет действительно полезной.

Заранее спасибо.


person iLearner    schedule 18.02.2016    source источник


Ответы (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.

person jpsim    schedule 19.02.2016
comment
Спасибо за ваш вклад, я попробую и вернусь к вам в случае каких-либо вопросов. - person iLearner; 22.02.2016
comment
в моем коде включен ARC, и я также добавил пул автовыпуска в метод VacuRealm, поэтому выпуск экземпляра Realm по-прежнему имеет значение. - person iLearner; 24.02.2016
comment
Должно быть что-то еще, обращающееся к Царству за пределами этого пула автоматического освобождения. Например, у вас может быть свойство, удерживающее объект Realm или Results, или саму Realm. Пожалуйста, отправьте сообщение о проблеме на github.com/realm/realm-cocoa/issues/new с полным описанием шагов воспроизведения, и мы будем рады помочь. - person jpsim; 25.02.2016