Очистить полную базу данных Realm

Я играю с областью (в настоящее время 0.85.0), и мое приложение использует базу данных для хранения пользовательских данных, таких как контакты текущего пользователя. Когда пользователь решает выйти из системы, мне нужно удалить каждый бит информации о пользователе, и, на мой взгляд, наиболее очевидной, простой и чистой вещью будет стереть всю область. К сожалению, Cocoa lib не предоставляет такой функциональности.

В настоящее время я застрял со следующим

RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm deleteObjects:[MyRealmClass1 allObjectsInRealm:realm]];
[realm deleteObjects:[MyRealmClass2 allObjectsInRealm:realm]];
[realm deleteObjects:[MyRealmClass3 allObjectsInRealm:realm]];
[realm commitWriteTransaction];

любые лучшие идеи?

спасибо


person floriankrueger    schedule 26.09.2014    source источник


Ответы (6)


Обновление:

После публикации был добавлен новый метод для удаления всех объектов (как уже упоминал jpsim):

// Obj-C
[realm beginWriteTransaction];
[realm deleteAllObjects];
[realm commitWriteTransaction];


// Swift
try! realm.write {
  realm.deleteAll()
}

Обратите внимание, что эти методы не изменят структуру данных; они только удаляют существующие записи. Если вы хотите изменить свойства модели области без написания миграции (т. Е. Как вы могли бы сделать в процессе разработки), старое решение, приведенное ниже, все еще может быть полезным.

Исходный ответ:

Вы можете просто удалить сам файл области, как это делается в их пример кода для хранения ответа REST:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //...

    // Ensure we start with an empty database
    [[NSFileManager defaultManager] removeItemAtPath:[RLMRealm defaultRealmPath] error:nil];

    //...
}

Обновление относительно вашего комментария:

Если вам нужно быть уверенным, что база данных области больше не используется, вы можете использовать уведомления области. Если бы вы увеличивали счетчик openWrites перед каждой записью, вы могли бы запускать блок после завершения каждой записи:

self.notificationToken = [realm addNotificationBlock:^(NSString *notification, RLMRealm * realm) {
    if([notification isEqualToString:RLMRealmDidChangeNotification]) {
        self.openWrites = self.openWrites - 1;

        if(!self.openWrites && self.isUserLoggedOut) {
            [[NSFileManager defaultManager] removeItemAtPath:[RLMRealm defaultRealmPath] error:nil];
        }
    }
}];
person uɥƃnɐʌuop    schedule 26.09.2014
comment
Да, я уже пробовал это, но проблема в том, что этот подход становится действительно неприятным, когда в фоновом режиме есть несколько потоков, которые пытаются что-то сделать в области, в то время как пользователь решает выйти из системы. Удаление файла на диске имеет тот недостаток, что оно игнорирует транзакции, которые могут быть открыты в данный момент, и в конечном итоге приводит к сбою приложения. И я действительно не хочу начинать синхронизировать все мои доступы к базе данных. В любом случае спасибо :) - person floriankrueger; 27.09.2014
comment
Привет, Тим из Realm. У DonamiteIsTnt правильная идея, но вы правы в том, что у этого подхода есть крайние случаи. Очень скоро мы представим метод безопасного удаления файлов области. Извини за это! - person timanglade; 28.09.2014
comment
@timanglade Есть что-нибудь о том, как продвигается этот метод? Кажется, я не могу его найти, но было бы неплохо иметь возможность просто удалить и воссоздать файл области. - person cjwirth; 10.02.2015
comment
@cjwirth, как описано ниже, здесь: realm.io/docs/cocoa/api/Classes/RLMRealm.html#//api/name/ - person timanglade; 11.02.2015
comment
Ах, спасибо... Я надеялся, что вы имели в виду API для удаления файла. Мы используем его только как кеш, и удалить/создать файл проще, чем иметь дело с миграциями. - person cjwirth; 11.02.2015
comment
На дворе 2016 год. @timanglade, есть ли безопасный способ удалить файл области и создать его заново? Некоторые из нас просто хотят с чистого листа, когда происходит изменение модели данных? - person okysabeni; 26.01.2016
comment
@okysabeni, вы правы, так как этот ответ был опубликован, метод именно для этой цели (ознакомьтесь с ответом jpsim выше). А именно [myRealm deleteAllObjects] в транзакции записи. Но старое решение, опубликованное в моем ответе, по-прежнему полезно для разработки. Я обновил, чтобы объяснить это. И спасибо за напоминание. - person uɥƃnɐʌuop; 26.01.2016
comment
Привет, Доанамит, спасибо! Я использовал ваш код для разработки. Проблема в пограничном случае, о котором говорил cjwirth. Он удалит файл, но в другом потоке он пытается записать в него, и это вызывает сбой. Он отлично работает, когда вы перезапускаете приложение, но это плохо для моих пользователей, если я это сделаю. - person okysabeni; 26.01.2016
comment
А, это имеет смысл. Да, в этом случае похоже, что deleteAll будет работать лучше, чем удаление файла, так как он не удаляет файл или его структуру данных. - person uɥƃnɐʌuop; 26.01.2016
comment
@timanglade нам нужен безопасный метод для удаления файлов области. какие-нибудь новости об эквиваленте deleteRealm, который есть в java? - person 2ank3th; 03.02.2016
comment
В настоящее время в Java нет возможности удалить все данные при сохранении схемы. В версии 0.88 будет метод Realm.clear(), который это сделает. На данный момент вам нужно перебрать все классы и сделать это вручную. Вы можете увидеть, как здесь: github.com/realm/realm-java/ вопросы/1796#issuecomment-157763025 - person Christian Melchior; 04.02.2016

RealmSwift: простой сброс с помощью флага

Пробовал приведенные выше ответы, но опубликовал еще один простой способ удалить файл области вместо переноса:

Realm.Configuration.defaultConfiguration.deleteRealmIfMigrationNeeded = true

Это просто устанавливает флаг, чтобы Realm мог удалить существующий файл, а не аварийно завершить работу на try! Realm().

Вместо удаления файла вручную

Думал, что это было проще, чем Swift-версия ответа выше:

guard let path = Realm.Configuration.defaultConfiguration.fileURL?.absoluteString else {
    fatalError("no realm path")
}

do {
    try NSFileManager().removeItemAtPath(path)
} catch {
    fatalError("couldn't remove at path")
}
person jonchoi    schedule 03.11.2016
comment
Я не знаю, в какой именно версии это было введено, но использование deleteRealmIfMigrationNeeded на самом деле сейчас правильно. - person floriankrueger; 04.11.2016

Начиная с области 0.87.0 теперь можно удалить всю область содержимое, вызвав [[RLMRealm defaultRealm] deleteAllObjects] из транзакции записи.

Из Swift это выглядит так: RLMRealm.defaultRealm().deleteAllObjects()

person jpsim    schedule 05.11.2014
comment
Этот не будет работать, если есть ожидающая миграция. Используйте ответ @DonamiteIsTnt, если хотите обойти миграцию - person Le Duc Duy; 24.01.2015

Если кто-то наткнется на этот вопрос, ища способ сделать это в Swift, это просто переписанный ответ DonamiteIsTnt. Я добавил эту функцию в собственный служебный класс, чтобы я мог выполнять MyAppUtilities.purgeRealm() во время тестирования и отладки.

func purgeRealm() {
    NSFileManager.defaultManager().removeItemAtPath(RLMRealm.defaultRealmPath(), error: nil)
}

Примечание. Если вам нужно очистить данные, вы можете просто воспользоваться новой функцией Realm realm.addOrUpdateObject(), которая позволяет заменить существующие данные по их первичному ключу новыми данными. Таким образом, вы не будете постоянно добавлять новые данные. Просто замена "старых" данных. Если вы используете addOrUpdateObject(), убедитесь, что вы переопределили функцию класса primaryKey вашей модели, чтобы Realm знал, какое свойство является вашим первичным ключом. В Свифте, например:

override class func primaryKey() -> String {
    return "_id"
}
person Glen Selle    schedule 09.10.2014

Я столкнулся с этой забавной маленькой проблемой. Поэтому вместо этого я запросил версию схемы непосредственно перед запуском миграции схемы.

NSError *error = NULL;
NSUInteger currentSchemaVersion = [RLMRealm schemaVersionAtPath:[RLMRealm defaultRealmPath] error:&error];
if (currentSchemaVersion == RLMNotVersioned) {
    // new db, skip

} else if (currentSchemaVersion < 26) {
    // kill local db
    [[NSFileManager defaultManager] removeItemAtPath:[RLMRealm defaultRealmPath] error:&error];
    if (error) {
        MRLogError(error);
    }

} else if (error) {
    // for good measure...
    MRLogError(error);
}

// perform realm migration
[RLMRealm setSchemaVersion:26
            forRealmAtPath:[RLMRealm defaultRealmPath]
        withMigrationBlock:^(RLMMigration *migration, NSUInteger oldSchemaVersion) {

        }];
person Steve Pascoe    schedule 27.05.2015

Вы также можете перейти в место, где хранится ваш файл области, удалить этот файл оттуда, и в следующий раз, когда вы откроете область после запуска приложения, вы увидите пустую базу данных области в браузере.

person Prathma Rastogi    schedule 07.03.2019