Очистить (удалить) базу данных в MagicalRecord

У меня есть приложение, которое использует MagicalRecord для обработки основных данных, и это работает хорошо. Однако у меня есть разные пользователи, которые могут войти в приложение и когда другой пользователь входит в систему, база данных основных данных должна быть опустошена, чтобы у другого пользователя могли быть свои собственные данные. База данных может быть полностью опустошена, поскольку данные также хранятся в веб-сервисе и поэтому всегда могут быть синхронизированы снова после входа в систему первого пользователя.

Пока что я не могу найти вспомогательный метод (который работает) для этой цели. я пытался

[MagicalRecord cleanUp];

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

15
Я не знаю, есть ли у Magical Record что-то для этого. Для этого вам нужно подождать автора. В любом случае, вы можете просто обойти его, удалив созданный файл db и вновь инициализируя стек через MagicalRecord. Возможно, в проекте MagicalRecord вы можете открыть запрос на перенос (требуется учетная запись GitHub).
добавлено автор Lorenzo B, источник

6 ответы

Вот как я это сделал. Крайне важно иметь эту строку: [Очистка MagicalRecord] . Без него [self setupDB] не будет работать.

UPDATE: Deletes the -wal and -shm files. @thattyson pointed out an issue in iOS 9. Also, see the answer of @onmyway133.

- (void)setupDB
{
    [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:[self dbStore]];
}

- (NSString *)dbStore
{
    NSString *bundleID = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
    return [NSString stringWithFormat:@"%@.sqlite", bundleID];
}

- (void)cleanAndResetupDB
{
    NSString *dbStore = [self dbStore];

    NSError *error1 = nil;
    NSError *error2 = nil;
    NSError *error3 = nil;

    NSURL *storeURL = [NSPersistentStore MR_urlForStoreName:dbStore];
    NSURL *walURL = [[storeURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-wal"];
    NSURL *shmURL = [[storeURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-shm"];

    [MagicalRecord cleanUp];

    if([[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error1] && [[NSFileManager defaultManager] removeItemAtURL:walURL error:&error2] && [[NSFileManager defaultManager] removeItemAtURL:shmURL error:&error3]){
        [self setupDB];
    }
    else{
        NSLog(@"An error has occurred while deleting %@", dbStore);
        NSLog(@"Error1 description: %@", error1.description);
        NSLog(@"Error2 description: %@", error2.description);
        NSLog(@"Error3 description: %@", error3.description);
    }
}

Вот версия Swift:

func setupDB() {
    MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreNamed(self.dbStore())
}

func dbStore() -> String {
    return "\(self.bundleID()).sqlite"
}

func bundleID() -> String {
    return NSBundle.mainBundle().bundleIdentifier!
}

func cleanAndResetupDB() {
    let dbStore = self.dbStore()

    let url = NSPersistentStore.MR_urlForStoreName(dbStore)
    let walURL = url.URLByDeletingPathExtension?.URLByAppendingPathExtension("sqlite-wal")
    let shmURL = url.URLByDeletingPathExtension?.URLByAppendingPathExtension("sqlite-shm")

    var removeError: NSError?

    MagicalRecord.cleanUp()

    //Swift 1
    //let deleteSuccess = NSFileManager.defaultManager().removeItemAtURL(url, error: &removeError)

    //Swift 2
    let deleteSuccess: Bool
    do {
        try NSFileManager.defaultManager().removeItemAtURL(url)
        try NSFileManager.defaultManager().removeItemAtURL(walURL!)
        try NSFileManager.defaultManager().removeItemAtURL(shmURL!)
        deleteSuccess = true
    } catch let error as NSError {
        removeError = error
        deleteSuccess = false
    }

    if deleteSuccess {
        self.setupDB()
    } else {
        println("An error has occured while deleting \(dbStore)")
        println("Error description: \(removeError?.description)")
    }
}
36
добавлено
но как насчет -shm и -wal-файлов? Те не удаляются таким образом, не так ли?
добавлено автор swalkner, источник
@thattyson, вы имели в виду, если ваш базовый SDK - это iOS 9?
добавлено автор yoninja, источник
@thattyson, это не сработало для меня, но оно дает неожиданные результаты - некоторые данные не сохраняются (правильно). Но, да, удаление файлов -wal и -shm становится необходимым.
добавлено автор yoninja, источник
@Wongzigii, что вы делали - что такое код - когда вы получили эту ошибку?
добавлено автор yoninja, источник
Я получаю эту ошибку Error1 description: Error Domain = NSCocoaErrorDomain Code = 4 "" ShoppingList "не удалось удалить."
добавлено автор Zigii Wong, источник
Не работает для меня. Я получаю следующую ошибку: «Операция не может быть выполнена. Нет такого файла или каталога»
добавлено автор Szu, источник
Начиная с iOS9, если вы не удаляете файлы -shm и -wal, ваше приложение будет сбой с кодом ошибки SQLite: 522 после попытки установить вашу БД второй раз.
добавлено автор thattyson, источник
@yoninja К сожалению, если ваш базовый SDK - это iOS 9 - удаление и настройка будут работать, но при попытке доступа к новой базе данных вы столкнетесь с ошибками и сбоями. Удаление -wal и -shm до self.setupDB() исправить это.
добавлено автор thattyson, источник

Чтобы расширить ответ на @yoninja, это сделает явным образом сброс стека CoreData, а также работу с файлами wal и shm

- (void)setupDB
{
    [MagicalRecord setDefaultModelNamed:@"Model.momd"];
    [MagicalRecord setupCoreDataStack];
}

- (void)cleanAndResetupDB
{
    [MagicalRecord cleanUp];

    NSString *dbStore = [MagicalRecord defaultStoreName];

    NSURL *storeURL = [NSPersistentStore MR_urlForStoreName:dbStore];
    NSURL *walURL = [[storeURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-wal"];
    NSURL *shmURL = [[storeURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-shm"];

    NSError *error = nil;
    BOOL result = YES;

    for (NSURL *url in @[storeURL, walURL, shmURL]) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:url.path]) {
            result = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
        }
    }

    if (result) {
        [self setupDB];
    } else {
        NSLog(@"An error has occurred while deleting %@ error %@", dbStore, error);
    }
}
20
добавлено
Спасибо, это работает для меня
добавлено автор lenhhoxung, источник
Почему эти неклассические функции?
добавлено автор Minimi, источник
Благодаря!!!! вы спасли меня!
добавлено автор Jordi Puigdellívol, источник
Это работает и для меня тоже, но иногда кажется, что личный контекст на фоне потоков остается болтающимся после выхода из системы. Любая идея, как я могу это исправить? Ценю вашу помощь.
добавлено автор Myxtic, источник

MagicalRecord не предоставляет вам эту функцию. Метод cleanUp предоставляется для повторной инициализации стека CoreData в памяти и очистки любых контекстов, очередей и других связанных объектов. Тем не менее, это не так сложно сделать самому, учитывая, что MagicalRecord предоставляет удобный метод для получения пути к вашей библиотеке.

Ознакомьтесь с методом - [NSPersistentStore MR_urlForStoreName:] . Это даст вам URL-адрес файла для вашего магазина. Затем вы можете удалить его с помощью экземпляра NSFileManager . Будьте осторожны, чтобы сделать это до того, как вы установите стек Core Data, или вы потерпите крах, когда вы сохраните, потому что вы вытащили хранилище из-за правильно инициализированного стека.

18
добавлено
Было ли это когда-либо добавлено к МР?
добавлено автор lostintranslation, источник
если вы видите мой комментарий, я предложил то же самое ;-) +1 для вашего более глубокого объяснения
добавлено автор Lorenzo B, источник
Я только что вставил новую проблему в GitHub. Приветствия.
добавлено автор Lorenzo B, источник
Спасибо, ребята, я это проверю!
добавлено автор Hugo, источник
Ваше предложение для запроса на вытаскивание или проблема на репо также приветствуется :)
добавлено автор casademora, источник

Следующее полностью удалит файлы sqlite MagicalRecord CoreData, а также файлы -wal и -shm. MagicalRecord помещает их все в папку Library; это просто удалит все файлы из папки. Это не сработает, если у вас есть другие данные, которые необходимо сохранить в папке «Библиотека», я не сделал этого:

- (void)resetCoreDataDB
{
    [MagicalRecord cleanUp];
    [self deleteFilesInLibrary];
    [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"YourDBName.sqlite"];
}

- (void)deleteFilesInLibraryDirectory
{
    NSString* folderPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSError *error = nil;
    for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error])
    {
        [[NSFileManager defaultManager] removeItemAtPath:[folderPath stringByAppendingPathComponent:file] error:&error];
        if(error)
        {
            NSLog(@"Delete error: %@", error.description);
        }
    }
}
5
добавлено

Если вы используете iOS Simulator и удалили файл базы данных, возможно, вы заметите, что данные все еще там. Однако, если он проверен на самом устройстве (что должно быть), файл будет удален, а контекст будет сброшен, как и должно быть.

[MagicalRecord cleanUp];

// delete database file
NSError *error;
NSURL *fileURL = [NSPersistentStore MR_urlForStoreName:@"db.sqlite"];
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error];
if(error) {
   //Hanldle error
}

// reset setup.
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"db.sqlite"];
2
добавлено
в iOS 9 после этого, а затем при сбое приложения, БД теряется ..
добавлено автор Jordi Puigdellívol, источник

Немного переписан ответ @yoninja для Swift 4 :

private var dbStore : String? {
    get {
        if let bundleId = Bundle.main.bundleIdentifier {
            return bundleId + ".sqlite"
        }
        return MagicalRecord.defaultStoreName()
    }
}

func setupCoreDataStack() {
    MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: self.dbStore)
}

func cleanUp() {        
    MagicalRecord.cleanUp()

    var removeError: NSError?
    let deleteSuccess: Bool
    do {
        guard let url = NSPersistentStore.mr_url(forStoreName: self.dbStore) else {
            return
        }
        let walUrl = url.deletingPathExtension().appendingPathExtension("sqlite-wal")
        let shmUrl = url.deletingPathExtension().appendingPathExtension("sqlite-shm")

        try FileManager.default.removeItem(at: url)
        try FileManager.default.removeItem(at: walUrl)
        try FileManager.default.removeItem(at: shmUrl)

        deleteSuccess = true
    } catch let error as NSError {
        removeError = error
        deleteSuccess = false
    }

    if deleteSuccess {
        self.setupCoreDataStack()
    } else {
        print("An error has occured while deleting \(self.dbStore)")
        print("Error description: \(removeError.debugDescription)")
    }
}
0
добавлено
Mobile Dev Jobs — вакансии и аналитика
Mobile Dev Jobs — вакансии и аналитика
6 187 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin и т.д. ВАЖНО: Правила публикации и правила канала: Ссылка – https://telegra.ph/Pravila-oformleniya-vakansij-i-rezyume-11-09-2

iOS Developers — русскоговорящее сообщество
iOS Developers — русскоговорящее сообщество
2 400 участник(ов)

Общаемся на темы, посвященным iOS-разработке, Swift, Objective-C, SDK, Rx, Cocoa и т.д.