コアデータのすべてのエントリを削除/リセットしますか?


235

Core Dataに保存されているすべてのエントリを削除する方法を知っていますか?私のスキーマは変わらないはずです。空白にリセットしたいだけです。


編集する

ユーザーが基本的にresetボタンを押すことができるように、これをプログラムで行うことを考えています。


6
以下の回答の多くは日付が付けられています。を使用しNSBatchDeleteRequestます。stackoverflow.com/a/31961330/3681880
Suragch

回答:


198

NSFileManager:removeItemAtPath ::メソッドを使用して、プログラムでファイルを削除することもできます。

NSPersistentStore *store = ...;
NSError *error;
NSURL *storeURL = store.URL;
NSPersistentStoreCoordinator *storeCoordinator = ...;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

次に、永続ストアを追加して、正しく再作成されるようにします。

各エンティティを反復処理するプログラムによる方法は、速度が遅く、エラーが発生しやすくなります。このように使用するのは、一部のエンティティを削除し、他のエンティティは削除しない場合です。ただし、参照整合性を維持する必要があります。そうしないと、変更を保持できなくなります。

ストアを削除して再作成するだけで、高速かつ安全であり、実行時にプログラムで確実に実行できます。

iOS5以降のアップデート

iOS 5およびOS X 10.7で外部バイナリストレージ(allowsExternalBinaryDataStorageまたは外部レコードファイルに保存)が導入されたため、storeURLsが指すファイルを削除するだけでは不十分です。外部レコードファイルは残しておきます。これらの外部レコードファイルの命名方式は公開されていないため、私にはまだ汎用的なソリューションがありません。– an0 5月8日'12月23:00


1
これはおそらく信頼性のための最良のソリューションです。:私はいくつかのではなく、すべてのデータを削除したい場合は、私はこの使用しますstackoverflow.com/questions/1077810/...
マイケルGrinich

12
storeCoordinatorを適切に取得する方法を知っています。ただし、persistentStoreを取得する方法がわかりません。だからあなただけではなく、適切な例を挙げてください:NSPersistentStore * store = ...;
Pascal Klein

11
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error]の方が優れています。
an0

3
@Pascalストアコーディネーターを取得できる場合は、persistentStoresプロパティを介してすべての永続ストアにアクセスできます。
ミハイダミアン

2
ここに新しい空のストアを再作成する方法を含むサンプルコード:stackoverflow.com/a/8467628
Joshua C. Lerner

140

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);
    }

}

テーブルごとに実行することを選択した理由は、プログラミングを行っているときに、テーブルの内容を削除することが賢明であり、保持したいデータがないことを確認するためです。

これを行うと、ファイルを削除するよりもかなり遅くなり、このメソッドに時間がかかりすぎる場合は、ファイルの削除に変更します。


素晴らしいソリューション。ありがとう。DLog()とは何ですか?
マイケル・グリニッチ、2009

ああそうです-ビルドがデバッグビルドの場合にのみNSLogを実行する特別な関数です。NSLogに置き換えてください。
Grouchal 2009

6
DLogの実装は次の場所で確認できます。cimgf.com/ 2009/01/24
Matt Long

3
これは私にとってはうまくいきます。しかし、それをより速くするために、1つのコマンドで特定のエンティティのすべてのオブジェクトを削除する方法はありますか?SQLの場合と同様に、DROP TABLE entity_nameなどを実行できます。他のエンティティではなく、特定のエンティティのすべてのオブジェクトを削除したいので、SQLファイル全体を削除したくありません。
ma11hew28 2010

8
NSDictionary * allEntities = _managedObjectModel.entitiesByName;を使用します。モデル内のすべてのエンティティを取得し、このNSDictionaryのキーを反復処理して、ストア内のすべてのエンティティを削除できます。
adam0101

60

iOS 10以降向けの更新されたソリューション

NSBatchDeleteRequestエンティティー内のすべてのオブジェクトをメモリにロードしたり、繰り返し処理したりすることなく削除するために使用します。

// create the delete request for the specified entity
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = MyEntity.fetchRequest()
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用に更新されています。iOS9をサポートする必要がある場合は、この質問を参照してください。

出典:


3
そのブロック全体をmoc.performBlockAndWait({ () -> Void in... 内に配置します})
SwiftArchitect 2015年

2
アプリが再起動されるか、NSBatchDeleteRequestを2回実行するまでエントリが削除されない理由を確認してください長い話ですが、エンティティがメモリに読み込まれている場合、上記のコードでは不十分です
Honey

38

私は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;

このメソッドは、coreDataHelpernilのときにpersistentStoreを作成することを(とりわけ)処理するクラスの内部にあります。


「セレクタ 'persistentStores'の既知のクラスメソッドはありません」
Aviram Netanel

27

私は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を呼び出すために、ホームビューコントローラーでプロパティを宣言したことに注意してください。(保存と読み込みに使用するmanagedObjectContextについては心配しないでください。)

@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;

@ayteat、これでうまくいきましたか?私にとっては機能しません。このstackoverflow.com/questions/14646595/…
Ranjit

1
これは、「AppDelegate * ad = [[UIApplication sharedApplication] delegate];」を使用することを除いて、答えです。自分自身を広告に置き換えます。コードの最後の2ビットをコピーしないでください
Cescy

1
managedObjectContextでリセットを呼び出さないのはなぜですか?managedObjectへの強い参照がある場合はどうなりますか?
Parag Bafna 2015年

@ParagBafna正解です。上記のコードサンプルは、管理対象オブジェクトへの強い参照がないことを前提としています。いくつかある場合は、managedObjectContextで 'reset'を呼び出して、所有しているすべての管理対象オブジェクトを逆参照する必要があります。
2015年

ねえ、ありがとう。また、アプリのアップグレード時にこれを行う方法はありますか?正確に言うと、私の要件は、次のバージョンのアプリをロールするとき、ユーザーがappStoreからアプリを更新するときに、コアデータとSQLiteファイルを削除して、空白に再初期化することです。NSUserDefaultsのBool値を使用してアプリの最初の起動イベントを検出し、アプリデリゲートのdidfinishLaunchingWithOptionsでこの値を確認する方法を見つけましたが、これらすべてをクリアする方法がわかりませんでした。ボタンがなく、アプリのデリゲートが上記のようにクリアするための「persistentStore」を検出していないため。ヘルプ?
Tejas

19

MagicalRecordはこれを非常に簡単にします。

[MyCoreDataObject MR_truncateAll];

16
これはかっこいいですが、CoreDataソリューションを指定したため、トピックとは関係ありませんでした
Michael Grinich、2011

8
Active Record Fetching コアデータソリューションです。
casademora 2011

7
しかし、このような答えは質問の範囲を超えています。彼がこれを行うために追加のフレームワークを使用したいと思う理由はありません。
jpswain 2011

これは質問の答えにはなりません。これは、すべてのエンティティではなく、1つのエンティティからエントリを削除するための良い方法です...!モデル内のすべてのエンティティをどのように列挙して送信MR_truncateAllしますか?
fatuhoku 2014

MR_truncateAllのソースを表示します(すべてのオブジェクトをフェッチしますが、NSMOを破棄するつもりなので)プロパティはフェッチしません。次に、指定したエンティティのオブジェクトを繰り返し処理して削除します。github.com/magicalpanda/MagicalRecord/blob/master/MagicalRecord/...
1in9ui5t

19

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)
        }
    }
}

1
アプリが再起動されるか、NSBatchDeleteRequestを2回実行するまでエントリが削除されない理由を確認してください長い話ですが、エンティティがメモリに読み込まれている場合、上記のコードでは不十分です
Honey

13

[新しい応答を求める報奨金に対する返答の遅れ]

以前の答えを見て、

  • @Grouchalや他の人が提案するように、すべてのアイテムを取得して削除することは、依然として効果的で有用なソリューションです。非常に大きなデータストアがある場合、速度は遅くなる可能性がありますが、それでも十分に機能します。
  • あなたと@groundhogが指摘しているように、データストアを削除するだけでは効果がありません。iOS 7はSQLiteジャーナリングにWALモードを使用するため、外部バイナリストレージを使用しなくても時代遅れです。WALモードでは、任意のCore Data永続ストア用の(潜在的に大きな)ジャーナルファイルが存在する可能性があります。

しかし、機能する永続ストアを削除するための別の同様のアプローチがあります。重要なのは、永続ストアファイルを、他に何も含まれていない独自のサブディレクトリに配置することです。ドキュメントディレクトリ(またはどこにでも)に固定するのではなく、永続ストア専用の新しいサブディレクトリを作成します。そのディレクトリの内容は、永続ストアファイル、ジャーナルファイル、および外部バイナリファイルになります。データストア全体をnukeする場合は、そのディレクトリを削除すると、すべて削除されます。

永続ストアを設定するときは、次のようにします。

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];

これにより、カスタムサブディレクトリとその中のすべてのCore Dataファイルの両方が再帰的に削除されます。

これは、永続ストアが他の重要なデータと同じフォルダーにない場合にのみ機能します。ドキュメントディレクトリのように、おそらく他の便利なものが含まれています。それがあなたの状況である場合は、保持たいファイルを探し、それ以外のものをすべて削除することで同じ効果を得ることができます。何かのようなもの:

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.
}

このアプローチはエラーが発生しやすくなる可能性があります。保持したいすべてのファイルを確実に把握しておく必要があります。そうしないと、重要なデータが削除される可能性があります。一方、外部バイナリファイルを保存するために使用されるファイル/ディレクトリ名を実際に知らなくても、外部バイナリファイルを削除できます。


walファイルが怖い場合は、無効にしてください
onmyway133 '27

11

これは、コアデータをパージするための統合ソリューションです。

- (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]);
        }
    }  
}

10

すべてのオブジェクトを削除し、バッキングファイルを削除したくない場合は、次の方法を使用できます。

- (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);
    }
}

非常に遅い場合があることに注意してください(オブジェクトグラフ内のオブジェクトの数によって異なります)。


アプリの更新時に古いデータ(たとえば、3つのテーブル、1つのテーブルからデータを削除する)を削除する方法
Madan Mohan

6

すべてのオブジェクトを削除するルートを実行する場合(これは、コアデータスタックを破棄するよりもはるかに簡単ですが、パフォーマンスは低くなります)、これはより良い実装です。

- (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は、メインスレッドから削除を実行し、完了時に通知するために活用します。完了ブロック内で通知または何かを発行して、ステータスをメインスレッドに戻すことができます。


あなたのNSManagedObjectContextは次のように初期化されなければならないことに注意してくださいNSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];、あなたがエラーを取得し、この方法または他のを使用するために:Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
ウィル

6

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()
        }
    }
}

すべてのコアデータエンティティを反復処理してクリアします


4

投稿ありがとうございます。私はそれに続き、それは私のために働いた。しかし、どの返信にも記載されていない別の問題がありました。だから私だけだったのかわかりません。

とにかく、私はここに問題とそれを解決する私の方法を投稿すると思いました。

データベースにいくつかのレコードがあったので、新しいデータをデータベースに書き込む前にすべてをきれいにしたかったので、

[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error]; 

その後managedObjectContext、データベースにアクセスするために使用されました(現時点では空であると想定されています)。どういうわけか、データはまだそこにありました。トラブルシューティングのしばらくして、私は私がリセットする必要があることがわかったmanagedObjectContextmanagedObjectmanagedObjectModelpersistentStoreCoordinator私は使用する前に、managedObjectContext dabaseにアクセスすること。これで、書き込み可能なクリーンなデータベースができました。


それで、managedObjectContext、managedObject、managedObjectModel、persistentStoreCoordinatorをリセットすると、データベースが含まれているファイルが削除された後に元に戻りますか?
Daniel Brower

4

これは、AppDelegate selfへの呼び出しが少ない、やや単純化されたバージョンで、最高評価の回答から除外されたコードの最後のビットです。また、「この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];
}

4

迅速な解決策:

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)
    }

let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "momd")!
Swift

3

他の場所で検索を保存するためのクイックリファレンスとして-永続ストアを削除した後に再作成するには、次のようにします。

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}

私はあなたのコードを試しましたが、xcodeはこの行で例外をスローします。
Ranjit 2013

3

この質問に対するいくつかの良い答え。ここに素敵な簡潔なものがあります。最初の2行は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];
}

1
この目的で委任を乱用しないでください。hollance.com
Michael Dorner

1
@MichaelDornerに同意します。AppDelegateに多くを追加すると、パフォーマンスに影響を及ぼし、AppDelegateを突然すべてのクラスに含める必要がある依存関係の相互接続されたクモの巣によってバイナリのサイズが膨らむ可能性があります。この問題が発生した場合は、この目的に固有の別のコントローラーを作成してください。AppDelegateは、アプリケーションの基本的な初期化と状態変更の処理のために残しておく必要があります。
jcpennypincher 2015

2

すべてのエンティティ名を検索して、名前で削除することもできます。その長いバージョンですが、正常に機能します。これにより、永続ストアを操作する必要がなくなります。

 - (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」の場合は、エンティティの名前のいずれか1つを指定するだけです。エンティティが含まれているエンティティの説明を理解するだけで済みます。ValueForKey @ "name"はすべてのエンティティ名を返します。最後に、保存することを忘れないでください。


2

NSFileManagerによるURLの削除は正しく、受け入れられた答えは正しいですが、iOS 5以降の編集で述べられているように、永続ストアは1つのファイルだけで表されるわけではありません。SQLiteストアの場合、*。sqlite、*。sqlite-shm、*。sqlite-walです...幸いiOS 7以降ではメソッドを使用できます

[NSPersistentStoreCoordinator + removeUbiquitousContentAndPersistentStoreAtURL:options:error:]

削除を処理するため、コードは次のようになります。

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];

2
オプションdict、特にストア名を渡す必要があります。例:@ {NSPersistentStoreUbiquitousContentNameKey:@ "MyData"};
tomi44g 2015

2

これは、あなたが持っているすべてのテーブルのすべてのレコードを削除するバージョンです。

スウィフト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)")
    }
}

2

Swift 4/5、iOS 9以降

CoreDataSQLiteファイル全体を再構築すると、すべてのデータが確実に消去されるため、すべてのエンティティが削除されます。電話するだけ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()
    }
}

これを使用している人は、SQLファイルがない場合に「初めて」クラッシュすることに注意してください(私の回答で「ガード」を使用しただけです)
Fattie

1

すべてのバージョンで動作します。エンティティ名を渡して繰り返し処理し、すべてのエントリを削除してコンテキストを保存します。

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)")
    }
}

1

(アプリの要件に基づいて)私がよく使用するもう1つの方法(バッチの削除リクエストを除く)は、永続ストアをリセットすることです。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)
        }
    }

}

この方法の利点の1つは、特にコアデータ内の多数のエンティティのデータレコードが大量にある場合に、より簡単になることです。この場合、バッチ削除リクエストはメモリを大量に消費します。


1

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)
    }
}

0

永続ストアファイルを削除し、新しい永続ストアコーディネーターをセットアップしますか?


6
ありがたいことに、クリーンを実行しても永続ストアファイルは削除されません。それが本当なら、それは災害のレシピです。
ハンター


0

あなたが使用していると仮定 MagicalRecordしていて、デフォルトの永続ストアがある:

特定のファイルが存在すると想定したり、エンティティ名やクラスの入力を要求したりするすべてのソリューションが好きではありません。これはSwift(2)であり、すべてのエンティティからすべてのデータを削除する安全な方法です。削除すると、新しいスタックも再作成されます(この部分がどれほど必要かについては、実際にはわかりません)。

すべてを削除したいが、(ユーザーがログインしたら...)新しいデータを取得するための作業ストアとmocがある「ログアウト」スタイルの状況では、これは非常に役立ちます。

extension NSManagedObject {

    class func dropAllData() {

        MagicalRecord.saveWithBlock({ context in

            for name in NSManagedObjectModel.MR_defaultManagedObjectModel().entitiesByName.keys {
                do { try self.deleteAll(name, context: context) }
                catch { print("⚠️ ✏️ Error when deleting \(name): \(error)") }
            }

            }) { done, err in
                MagicalRecord.cleanUp()
                MagicalRecord.setupCoreDataStackWithStoreNamed("myStoreName")
        }
    }

    private class func deleteAll(name: String, context ctx: NSManagedObjectContext) throws {
        let all = NSFetchRequest(entityName: name)
        all.includesPropertyValues = false

        let allObjs = try ctx.executeFetchRequest(all)
        for obj in allObjs {
            obj.MR_deleteEntityInContext(ctx)
        }

    }
}

0

これを使って

+(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];
}

0

私は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);
    }
}

0

ここで、すべてのレコードを削除するための私の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
    }   
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.