Удалить / Сбросить все записи в Базовых данных?
Знаете ли вы какой-либо способ удалить все записи, хранящиеся в основных данных? Моя схема должна остаться прежней; Я просто хочу сбросить его до пустого.
редактировать
Я хочу сделать это программно, чтобы пользователь мог по существу ударить reset
кнопка.
29 ответов
Вы все еще можете удалить файл программно, используя NSFileManager:removeItemAtPath:: method.
NSPersistentStore *store = ...;
NSError *error;
NSURL *storeURL = store.URL;
NSPersistentStoreCoordinator *storeCoordinator = ...;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
Затем просто добавьте постоянное хранилище обратно, чтобы убедиться, что оно воссоздано правильно.
Программный способ перебора каждой сущности медленнее и подвержен ошибкам. Это можно сделать, если вы хотите удалить некоторые объекты, а не другие. Однако вы все равно должны убедиться, что сохраняете ссылочную целостность, иначе вы не сможете сохранить свои изменения.
Простое удаление и воссоздание хранилища является быстрым и безопасным, и, безусловно, может быть сделано программно во время выполнения.
Обновление для iOS5+
С введением внешнего двоичного хранилища (allowExternalBinaryDataStorage или Store во внешнем файле записи) в iOS 5 и OS X 10.7 простого удаления файлов, указанных в storeURL, стало недостаточно. Вы оставите внешние файлы записи позади. Поскольку схема именования этих внешних файлов записи не является общедоступной, у меня пока нет универсального решения. - до 8 мая '12 в 23:00
Вы можете удалить файл SQLite, но я решил сделать это, удалив таблицы по отдельности с помощью функций:
- (void) deleteAllObjects: (NSString *) entityDescription {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityDescription inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *items = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
for (NSManagedObject *managedObject in items) {
[_managedObjectContext deleteObject:managedObject];
DLog(@"%@ object deleted",entityDescription);
}
if (![_managedObjectContext save:&error]) {
DLog(@"Error deleting %@ - error:%@",entityDescription,error);
}
}
Причина, по которой я решил сделать это таблица за таблицей, заключается в том, что во время программирования я подтверждаю, что удаление содержимого таблицы является разумным, и нет данных, которые я бы предпочел хранить.
Делать это будет намного медленнее, чем просто удалить файл, и я перейду на удаление файла, если этот метод займет слишком много времени.
Обновленное решение для iOS 9+
использование NSBatchDeleteRequest
удалить все объекты в объекте, не загружая их в память или не просматривая их.
// create the delete request for the specified entity
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "MyEntity")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
// get reference to the persistent container
let persistentContainer = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
// perform the delete
do {
try persistentContainer.viewContext.execute(deleteRequest)
} catch let error as NSError {
print(error)
}
Этот код был обновлен для iOS 10 и Swift 3. Если вам нужна поддержка iOS 9, посмотрите этот вопрос.
Источники:
- Базовые данные: самый быстрый способ удалить все экземпляры объекта (включая код Objective-C)
- Что нового в основных данных (видео WWDC 2015)
- Что нового в основных данных (видео WWDC 2016)
- Как использовать базовые данные в iOS 10
- Что нового в Core Data Swift 3.0
Я написал clearStores
метод, который проходит через каждое хранилище и удаляет его как из координатора, так и из файловой системы (обработка ошибок оставлена в стороне):
NSArray *stores = [persistentStoreCoordinator persistentStores];
for(NSPersistentStore *store in stores) {
[persistentStoreCoordinator removePersistentStore:store error:nil];
[[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
}
[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
Этот метод находится внутри coreDataHelper
класс, который заботится (помимо прочего) о создании persistentStore, когда он равен нулю.
Я удаляю все данные из основных данных кнопки Event в классе HomeViewController: эта статья мне очень помогла, и я решила, что внесу свой вклад.
-(IBAction)buttonReset:(id)sender
{
NSLog(@"buttonReset Pressed");
//Erase the persistent store from coordinator and also file manager.
NSPersistentStore *store = [self.persistentStoreCoordinator.persistentStores lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
[self.persistentStoreCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
NSLog(@"Data Reset");
//Make new persistent store for future saves (Taken From Above Answer)
if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
}
Обратите внимание, что для вызова self.persistentStoreCoordinator я объявил свойство в Home View Controller. (Не беспокойтесь по поводу управляемого ObjectContext, который я использую для сохранения и загрузки.)
@property (nonatomic, retain) NSManagedObjectContext * managedObjectContext;
@property (nonatomic, retain) NSPersistentStoreCoordinator * persistentStoreCoordinator;
Затем в AppDelegate ApplicationDidFinishLaunching прямо ниже создания HomeViewController у меня есть:
homeViewController = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
homeViewController.managedObjectContext = self.managedObjectContext;
homeViewController.persistentStoreCoordinator = self.persistentStoreCoordinator;
iOS9+, Swift 2
Удалить все объекты во всех объектах
func clearCoreDataStore() {
let entities = managedObjectModel.entities
for entity in entities {
let fetchRequest = NSFetchRequest(entityName: entity.name!)
let deleteReqest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try context.executeRequest(deleteReqest)
} catch {
print(error)
}
}
}
MagicalRecord делает это очень легко.
[MyCoreDataObject MR_truncateAll];
[Поздний ответ в ответ на награду за новые ответы]
Просматривая предыдущие ответы,
- Выборка и удаление всех элементов, как предлагает @Grouchal и другие, по-прежнему является эффективным и полезным решением. Если у вас очень большие хранилища данных, то это может быть медленно, но все равно работает очень хорошо.
- Как вы и @groundhog заметили, простое удаление хранилища данных больше не эффективно. Он устарел, даже если вы не используете внешнее двоичное хранилище, потому что iOS 7 использует режим WAL для журналирования SQLite. В режиме WAL могут храниться (потенциально большие) файлы журналов для любого постоянного хранилища Core Data.
Но есть другой, похожий подход к удалению постоянного хранилища, которое работает. Ключ должен поместить ваш постоянный файл хранилища в его собственный подкаталог, который не содержит ничего другого. Не просто вставьте его в каталог документов (или где-либо еще), создайте новый подкаталог только для постоянного хранилища. Содержимое этого каталога в конечном итоге станет файлом постоянного хранилища, файлами журнала и внешними двоичными файлами. Если вы хотите уничтожить все хранилище данных, удалите этот каталог, и все они исчезнут.
Вы бы сделали что-то подобное при настройке вашего постоянного магазина:
NSURL *storeDirectoryURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"persistent-store"];
if ([[NSFileManager defaultManager] createDirectoryAtURL:storeDirectoryURL
withIntermediateDirectories:NO
attributes:nil
error:nil]) {
NSURL *storeURL = [storeDirectoryURL URLByAppendingPathComponent:@"MyApp.sqlite"];
// continue with storeURL as usual...
}
Затем, когда вы хотели удалить магазин,
[[NSFileManager defaultManager] removeItemAtURL:storeDirectoryURL error:nil];
Это рекурсивно удаляет как пользовательский подкаталог, так и все файлы базовых данных в нем.
Это работает, только если у вас нет постоянного хранилища в той же папке, что и другие важные данные. Как каталог документов, в котором, вероятно, есть другие полезные вещи. Если это ваша ситуация, вы можете получить тот же эффект, найдя файлы, которые вы хотите сохранить, и удалив все остальное. Что-то вроде:
NSString *docsDirectoryPath = [[self applicationDocumentsDirectory] path];
NSArray *docsDirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:docsDirectoryPath error:nil];
for (NSString *docsDirectoryItem in docsDirectoryContents) {
// Look at docsDirectoryItem. If it's something you want to keep, do nothing.
// If it's something you don't recognize, remove it.
}
Этот подход может быть подвержен ошибкам. Вы должны быть абсолютно уверены, что знаете каждый файл, который хотите сохранить, потому что в противном случае вы можете удалить важные данные. С другой стороны, вы можете удалить внешние двоичные файлы, фактически не зная имени файла / каталога, используемого для их хранения.
Вот комбинированное решение для очистки Core Data.
- (void)deleteAllObjectsInCoreData
{
NSArray *allEntities = self.managedObjectModel.entities;
for (NSEntityDescription *entityDescription in allEntities)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entityDescription];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSError *error;
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"Error requesting items from Core Data: %@", [error localizedDescription]);
}
for (NSManagedObject *managedObject in items) {
[self.managedObjectContext deleteObject:managedObject];
}
if (![self.managedObjectContext save:&error]) {
NSLog(@"Error deleting %@ - error:%@", entityDescription, [error localizedDescription]);
}
}
}
Если вы хотите удалить все объекты и не хотите удалять файлы поддержки, вы можете использовать следующие методы:
- (void)deleteAllObjectsInContext:(NSManagedObjectContext *)context
usingModel:(NSManagedObjectModel *)model
{
NSArray *entities = model.entities;
for (NSEntityDescription *entityDescription in entities) {
[self deleteAllObjectsWithEntityName:entityDescription.name
inContext:context];
}
}
- (void)deleteAllObjectsWithEntityName:(NSString *)entityName
inContext:(NSManagedObjectContext *)context
{
NSFetchRequest *fetchRequest =
[NSFetchRequest fetchRequestWithEntityName:entityName];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSError *error;
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *managedObject in items) {
[context deleteObject:managedObject];
NSLog(@"Deleted %@", entityName);
}
}
Помните, что это может быть очень медленно (зависит от того, сколько объектов находится в вашем графе объектов).
Решение iOS 10 + Swift 3:
func clearCoreDataStore() {
let delegate = UIApplication.shared.delegate as! AppDelegate
let context = delegate.persistentContainer.viewContext
for i in 0...delegate.persistentContainer.managedObjectModel.entities.count-1 {
let entity = delegate.persistentContainer.managedObjectModel.entities[i]
do {
let query = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
let deleterequest = NSBatchDeleteRequest(fetchRequest: query)
try context.execute(deleterequest)
try context.save()
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
abort()
}
}
}
Перебирает все основные объекты данных и очищает их
Swift 4/5, iOS 9+
Восстановление всего CoreData
Файл SQLite обеспечит удаление всех данных, поэтому все объекты будут удалены. Просто позвониdeleteAndRebuild()
.
class CoreDataStack {
// Change this
static let datamodelName = "ProjectName"
static let storeType = "sqlite"
static let persistentContainer = NSPersistentContainer(name: datamodelName)
private static let url: URL = {
let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")
assert(FileManager.default.fileExists(atPath: url.path))
return url
}()
static func loadStores() {
persistentContainer.loadPersistentStores(completionHandler: { (nsPersistentStoreDescription, error) in
if let error = error {
fatalError(error.localizedDescription)
}
})
}
static func deleteAndRebuild() {
try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)
loadStores()
}
}
Если вы хотите пойти по пути удаления всех объектов (что гораздо проще, чем разбить стек основных данных, но менее производительно), то это будет лучшая реализация:
- (void)deleteAllManagedObjectsInModel:(NSManagedObjectModel *)managedObjectModel context:(NSManagedObjectContext *)managedObjectContext
{
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
[managedObjectContext performBlockAndWait:^{
for (NSEntityDescription *entity in managedObjectModel) {
NSFetchRequest *fetchRequest = [NSFetchRequest new];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesSubentities:NO];
NSArray *objects = [managedObjectContext executeFetchRequest:fetchRequest error:nil];
for (NSManagedObject *managedObject in objects) {
[managedObjectContext deleteObject:managedObject];
}
}
[managedObjectContext save:nil];
}];
}];
[operation setCompletionBlock:^{
// Do stuff once the truncation is complete
}];
[operation start];
}
Эта реализация использует NSOperation
выполнить удаление из основного потока и уведомить о завершении. Возможно, вы захотите отправить уведомление или что-то в блоке завершения, чтобы отправить статус обратно в главный поток.
Спасибо за пост. Я следовал за этим, и это работало на меня. Но у меня была другая проблема, которая не была упомянута ни в одном из ответов. Так что я не уверен, что это был только я.
Во всяком случае, думал, что я опубликую здесь проблему и мой путь, который решил ее.
У меня было несколько записей в базе данных, я хотел очистить все, прежде чем записывать новые данные в БД, поэтому я сделал все, включая
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
а затем использовал managedObjectContext
чтобы получить доступ к базе данных (которая должна быть пустой сейчас), каким-то образом данные все еще были там. Через некоторое время устранения неполадок я обнаружил, что мне нужно сбросить managedObjectContext
, managedObject
, managedObjectModel
а также persistentStoreCoordinator
прежде чем я использую managedObjectContext
чтобы получить доступ к базе данных. Теперь у меня есть чистая база данных для записи.
Быстрое решение:
class func deleteAllManagedObjects() {
let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "mom")
let mom = NSManagedObjectModel(contentsOfURL: modelURL)
for entityName in mom.entitiesByName.keys {
let fr = NSFetchRequest(entityName: entityName as String)
let a = Utility.managedObjectContext().executeFetchRequest(fr, error: nil) as [NSManagedObject]
for mo in a {
Utility.managedObjectContext().deleteObject(mo)
}
}
Utility.managedObjectContext().save(nil)
}
Вот версия, которая удаляет каждую запись в каждой вашей таблице.
Swift 4
static func resetDatabase() {
do {
try dataStore.persistentStoreCoordinator.managedObjectModel.entities.forEach { (entity) in
if let name = entity.name {
let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: name)
let request = NSBatchDeleteRequest(fetchRequest: fetch)
try mainContext.execute(request)
}
}
try mainContext.save()
} catch {
print("error resenting the database: \(error.localizedDescription)")
}
}
Вот несколько упрощенная версия с меньшим количеством обращений к самому AppDelegate и последним кусочком кода, который остался за пределами рейтинга. Также я получаю сообщение об ошибке "Постоянное хранилище объекта недоступно из этого координатора NSManagedObjectContext", поэтому просто нужно добавить его обратно.
NSPersistentStoreCoordinator *storeCoordinator = [self persistentStoreCoordinator];
NSPersistentStore *store = [[storeCoordinator persistentStores] lastObject];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"dataModel"];
NSError *error;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
if (storeCoordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:storeCoordinator];
}
Несколько хороших ответов на этот вопрос. Вот хороший лаконичный. Первые две строки удаляют базу данных sqlite. Затем цикл for: удаляет все объекты в памяти managedObjectContext.
NSURL *storeURL = [[(FXYAppDelegate*)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory] URLByAppendingPathComponent:@"AppName.sqlite"];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
for (NSManagedObject *ct in [self.managedObjectContext registeredObjects]) {
[self.managedObjectContext deleteObject:ct];
}
В качестве краткого справочника для сохранения поиска в другом месте - воссоздание постоянного хранилища после удаления может быть выполнено с помощью:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
Вы также можете найти все имена сущностей и удалить их по имени. Это более длинная версия, но работает хорошо, так что вам не нужно работать с сохранением хранилища
- (void)clearCoreData
{
NSError *error;
NSEntityDescription *des = [NSEntityDescription entityForName:@"Any_Entity_Name" inManagedObjectContext:_managedObjectContext];
NSManagedObjectModel *model = [des managedObjectModel];
NSArray *entityNames = [[model entities] valueForKey:@"name"];
for (NSString *entityName in entityNames){
NSFetchRequest *deleteAll = [NSFetchRequest fetchRequestWithEntityName:entityName];
NSArray *matches = [self.database.managedObjectContext executeFetchRequest:deleteAll error:&error];
}
if (matches.count > 0){
for (id obj in matches){
[_managedObjectContext deleteObject:obj];
}
[self.database.managedObjectContext save:&error];
}
}
для "Any_Entity_Name" просто укажите любое имя вашей сущности, нам нужно только выяснить описание сущности, в которой находятся ваши сущности. ValueForKey@"name" вернет все имена сущностей. Наконец, не забудьте сохранить.
Принятый ответ правильный с удалением URL с помощью NSFileManager, но как указано в iOS 5+ edit, постоянное хранилище не представлено только одним файлом. Для хранилища SQLite это *.sqlite, *.sqlite-shm и *.sqlite-wal ... к счастью, начиная с iOS 7+ мы можем использовать метод
[NSPersistentStoreCoordinator +removeUbiquitousContentAndPersistentStoreAtURL: параметры: ошибка:]
позаботиться об удалении, поэтому код должен быть примерно таким:
NSPersistentStore *store = ...;
NSError *error;
NSURL *storeURL = store.URL;
NSString *storeName = ...;
NSPersistentStoreCoordinator *storeCoordinator = ...;
[storeCoordinator removePersistentStore:store error:&error];
[NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:storeURL.path options:@{NSPersistentStoreUbiquitousContentNameKey: storeName} error:&error];
Решение Swift 5.1
public static func reset() {
let coordinator = _persistentContainer.persistentStoreCoordinator
for store in coordinator.persistentStores where store.url != nil {
try? coordinator.remove(store)
try? FileManager.default.removeItem(atPath: store.url!.path)
}
}
Еще один метод (помимо пакетного запроса на удаление), который я часто использую (в зависимости от требований приложения), - это сброс постоянного хранилища. Реализация для iOS 10+ и Swift выглядит так (при условии, что у вас есть класс CoreDataManager):
let persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "<Data-Model-Name>“)
container.loadPersistentStores(completionHandler: { (storeDescription, err) in
if let err = err {
fatalError("loading of store failed: \(err)")
}
})
return container
}()
func resetPersistentStore() {
if let persistentStore = persistentContainer.persistentStoreCoordinator.persistentStores.last {
let storeURL = persistentContainer.persistentStoreCoordinator.url(for: persistentStore)
do {
try persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: storeURL, ofType: NSSQLiteStoreType, options: nil)
} catch {
print("failed to destroy persistent store:", error.localizedDescription)
}
do {
try persistentContainer.persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
} catch {
print("failed to re-add persistent store:", error.localizedDescription)
}
}
}
Одним из преимуществ этого метода является то, что он более простой, особенно когда у вас есть множество записей данных для множества сущностей в ваших основных данных. В этом случае пакетный запрос на удаление потребует много памяти.
Работает со всеми версиями. Передайте имя сущности и выполните итерацию, чтобы удалить все записи и сохранить контекст.
func deleteData(entityToFetch: String, completion: @escaping(_ returned: Bool) ->()) {
var context = NSManagedObjectContext()
if #available(iOS 10.0, *) {
context = self.persistentContainer.viewContext
} else {
context = self.managedObjectContext
}
let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
fetchRequest.entity = NSEntityDescription.entity(forEntityName: entityToFetch, in: context)
fetchRequest.includesPropertyValues = false
do {
let results = try context.fetch(fetchRequest) as! [NSManagedObject]
for result in results {
context.delete(result)
}
try context.save()
completion(true)
} catch {
completion(false)
print("fetch error -\(error.localizedDescription)")
}
}
Кажется, есть два подхода:
Допустим, у вас есть типичный синглтон для основного стека данных.
import CoreData
public let core = Core.shared
public final class Core {
static let shared = Core()
var container: NSPersistentContainer!
private init() {
container = NSPersistentContainer(name: "stuff")
//deleteSql()
container.loadPersistentStores { storeDescription, error in
if let error = error { print("Error loading... \(error)") }
}
//deleteAll()
}
func saveContext() { // typical save helper
if container.viewContext.hasChanges {
do { try container.viewContext.save()
} catch { print("Error saving... \(error)") }
}
}
тогда...
func deleteSql() {
let url = FileManager.default.urls(
for: .applicationSupportDirectory,
in: .userDomainMask)[0].appendingPathComponent( "stuff.sqlite" )
guard FileManager.default.fileExists(atPath: url.path) else {
print("nothing to delete!")
return
}
do {
try container.persistentStoreCoordinator.destroyPersistentStore(
at: url, ofType: "sqlite", options: nil)
print("totally scorched the sql file. you DO now have to LOAD again")
}
catch {
print("there was no sql file there!")
}
}
func deleteAll() { // courtesy @Politta
for e in container.persistentStoreCoordinator.managedObjectModel.entities {
let r = NSBatchDeleteRequest(
fetchRequest: NSFetchRequest(entityName: e.name ?? ""))
let _ = try? container.viewContext.execute(r)
}
saveContext()
print("conventionally deleted everything from within core data. carry on")
}
}
.
1. обжечь sql файл
Любезно предоставлен отличный ответ @JDoe. Вы полностью уничтожаете sql файл.
Вы должны сделать это
- перед загрузкой основных данных, т.е. после создания контейнера, но
- перед фактической загрузкой магазинов.)
(Обратите внимание, что пример строки кода "//deleteSql()" находится непосредственно перед инициализацией.)
2. удалить все по одному в основных данных
Любезно отличный ответ @Politta. Вы можете сделать это в любое время после того, как основные данные будут запущены.
(Обратите внимание на пример строки кода "//deleteAll()" после инициализации.)
Первый подход, вероятно, более полезен при разработке. Второй подход, вероятно, более полезен в производственной среде (в относительно необычном случае, когда по какой-то причине вам нужно все стереть).
Удалить файл постоянного хранилища и настроить новый координатор постоянного хранилища?
Здесь моя версия swift3 для удаления всех записей. "Пользователи" - это имя объекта
@IBAction func btnDelAll_touchupinside(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchReq = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
let req = NSBatchDeleteRequest(fetchRequest: fetchReq)
do {
try managedObjectContext.execute(req)
} catch {
// Error Handling
}
}
Я взял код Grouchal и для его ускорения я использовал перечисление с параллельным режимом (NSEnumerationConcurrent
) он стал немного быстрее по сравнению с циклом for (в моем приложении я добавил эту функцию для тестеров, чтобы они могли очищать данные и выполнять тестовые случаи, а не удалять и устанавливать приложение)
- (void)resetObjects
{
[self deleteAllObjectsInEntity:@"Entity1"];
[self deleteAllObjectsInEntity:@"Entity2"];
[self deleteAllObjectsInEntity:@"Entity3"];
[self deleteAllObjectsInEntity:@"Entity4"];
}
-(void) deleteAllObjectsInEntity:(NSString*) entityName
{
MainDataContext *coreDataContext = [MainDataContext sharedInstance];
NSManagedObjectContext *currentContext = coreDataContext.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:currentContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *items = [currentContext executeFetchRequest:fetchRequest error:&error];
[items enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSManagedObject * obj, NSUInteger idx, BOOL *stop) {
[currentContext deleteObject:obj];
}];
if (![currentContext save:&error]) {
NSLog(@"Error deleting %@ - error:%@",entityName,error);
}
}
Использовать этот
+(NSArray *)fetchDataFromEntity:(NSString *)entityName context:(NSManagedObjectContext *)context
{
NSFetchRequest * fetchRequest =[[NSFetchRequest alloc] init];
NSEntityDescription * CategoriesEntity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[fetchRequest setEntity:CategoriesEntity];
NSError * error;
NSInteger count = [context countForFetchRequest:fetchRequest error:&error];
if (count && count>0) {
NSArray * fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects && fetchedObjects.count>0) {
return fetchedObjects;
}else
return nil;
}
else
return nil;
}
+ (void)deleteObjectsOfArray:(NSMutableArray*)ary context:(NSManagedObjectContext *)context {
for (NSManagedObject * obj in ary) {
[context deleteObject:obj];
}
NSError *saveError = nil;
[context save:&saveError];
}
+ (void)deleteEntity:(NSString *)entityName context:(NSManagedObjectContext *)context {
NSArray *listArray = [self fetchDataFromEntity:entityName context:context];
[self deleteObjectsOfArray:[NSMutableArray arrayWithArray:listArray] context:context];
}