Core Data に保存されているすべてのエントリを削除する方法を知っていますか? 私のスキーマは同じままである必要があります。空白にリセットしたいだけです。
編集
ユーザーが基本的にreset
ボタンを押すことができるように、これをプログラムで実行しようとしています。
Core Data に保存されているすべてのエントリを削除する方法を知っていますか? 私のスキーマは同じままである必要があります。空白にリセットしたいだけです。
編集
ユーザーが基本的にreset
ボタンを押すことができるように、これをプログラムで実行しようとしています。
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 または外部レコード ファイルへの保存) の導入により、storeURL が指すファイルを単に削除するだけでは十分ではありません。外部記録ファイルはそのままにしておきます。これらの外部レコード ファイルの命名規則は公開されていないため、まだ普遍的な解決策はありません。— an0 12 年 5 月 8 日 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);
}
}
テーブルごとに行うことを選択した理由は、プログラミングを行っているときに、テーブルの内容を削除することが賢明であり、保持したいデータがないことを確認できるためです。
これを行うと、ファイルを削除するよりもはるかに遅くなります。この方法に時間がかかりすぎる場合は、ファイルの削除に変更します。
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
、(特に) nil のときに persistStore を作成する処理を行うクラス内にあります。
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 でプロパティを宣言したことに注意してください。(保存と読み込みに使用する 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;
iOS9+、Swift2
すべてのエンティティのすべてのオブジェクトを削除する
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];
[新しい回答を求めるバウンティへの回答が遅れた]
過去の回答を見返してみると、
しかし、機能する永続ストアを削除する別の同様のアプローチがあります。重要なのは、永続ストア ファイルを、他に何も含まない独自のサブディレクトリに配置することです。ドキュメント ディレクトリ (または任意の場所) に貼り付けるだけでなく、永続ストア専用の新しいサブディレクトリを作成します。そのディレクトリの内容は、永続ストア ファイル、ジャーナル ファイル、および外部バイナリ ファイルになります。データ ストア全体を削除したい場合は、そのディレクトリを削除すると、すべてが消えます。
永続ストアを設定するときは、次のようにします。
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.
}
このアプローチは、エラーが発生しやすい可能性があります。重要なデータを削除してしまう可能性があるため、保持したいすべてのファイルを確実に把握しておく必要があります。一方、保存に使用されたファイル/ディレクトリ名を実際に知らなくても、外部バイナリ ファイルを削除できます。
これは、コア データをパージするための組み合わせソリューションです。
- (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()
}
}
}
すべてのコア データ エンティティを繰り返し処理し、それらをクリアします。
すべてのオブジェクトを削除するルート (コア データ スタックを破棄するよりもはるかに簡単ですが、パフォーマンスは劣ります) に進みたい場合は、これよりも優れた実装です。
- (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
この実装は、メイン スレッドから削除を実行し、完了時に通知するために活用します。ステータスをメインスレッドに戻すために、完了ブロック内で通知または何かを送信することができます。
迅速な解決策:
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)
}
投稿ありがとうございます。私はそれに従いました、そしてそれは私のために働きました。しかし、どの返信にも記載されていない別の問題がありました。だから、それが私だけだったのかどうかはわかりません。
とにかく、問題とそれを解決した方法をここに投稿すると思いました。
データベースにいくつかのレコードがありました。新しいデータをデータベースに書き込む前に、すべてをきれいにパージしたかったので、次のことをすべて行いました。
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
その後managedObjectContext
、データベースにアクセスするために使用されました(今では空になっているはずです)が、どういうわけかデータがまだそこにありました。しばらくトラブルシューティングを行った後、を使用してデータベースにアクセスする前にmanagedObjectContext
、 、managedObject
、managedObjectModel
および
をリセットする必要があることがわかりました。これで、書き込むためのクリーンなデータベースができました。 persistentStoreCoordinator
managedObjectContext
これは、 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];
}
他の場所で検索を保存するためのクイック リファレンスとして、削除後に永続ストアを再作成するには、次のコマンドを使用します。
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
この質問に対するいくつかの良い答え。ここに簡潔なものがあります。最初の 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];
}
また、すべてのエンティティ名を検索して、名前で削除することもできます。その長いバージョンですが、うまく機能します。そうすれば、永続ストアを操作する必要がありません。
- (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"は、すべてのエンティティ名を返します。最後に、保存することを忘れないでください。
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)
}
}
MagicalRecord
デフォルトの永続ストアを使用していると仮定します。
特定のファイルが存在すると仮定したり、エンティティ名やクラスの入力を要求したりするすべてのソリューションが好きではありません。これは、すべてのエンティティからすべてのデータを削除する Swift(2) の安全な方法です。削除した後、新しいスタックも再作成されます(この部分がどれほど必要かは実際にはわかりません)。
すべてを削除したいが、新しいデータを取得するための作業ストアとモックがある場合の「ログアウト」スタイルの状況には最適です(ユーザーがログインすると...)
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)
}
}
}
これを使って
+(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];
}
fileURLPath から sqlite を削除してからビルドします。
永続ストア ファイルを削除し、新しい永続ストア コーディネータをセットアップしますか?
あなたは皆、これを複雑に見えるようにしています。NSManagedObjectContextにリセットメソッドを送信するだけです