Hapus / Reset semua entri dalam Data Inti?

235

Apakah Anda tahu cara untuk menghapus semua entri yang disimpan dalam Data Inti? Skema saya harus tetap sama; Saya hanya ingin mengatur ulang ke kosong.


Edit

Saya mencari untuk melakukan ini secara terprogram sehingga pengguna pada dasarnya dapat menekan resettombol.

Michael Grinich
sumber
6
Banyak jawaban di bawah ini yang bertanggal. Gunakan NSBatchDeleteRequest. stackoverflow.com/a/31961330/3681880
Suragch

Jawaban:

198

Anda masih dapat menghapus file secara terprogram, menggunakan metode NSFileManager: removeItemAtPath ::.

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

Kemudian, tambahkan saja toko persisten kembali untuk memastikan itu dibuat kembali dengan benar.

Cara terprogram untuk iterasi melalui masing-masing entitas lebih lambat dan rentan terhadap kesalahan. Penggunaan untuk melakukannya dengan cara itu adalah jika Anda ingin menghapus beberapa entitas dan bukan yang lain. Namun Anda masih perlu memastikan bahwa Anda mempertahankan integritas referensial atau Anda tidak akan dapat mempertahankan perubahan Anda.

Hanya menghapus toko dan membuatnya kembali cepat dan aman, dan tentu saja dapat dilakukan secara terprogram saat runtime.

Pembaruan untuk iOS5 +

Dengan diperkenalkannya penyimpanan biner eksternal (memungkinkanExternalBinaryDataStorage atau Simpan di File Rekaman Eksternal) di iOS 5 dan OS X 10.7, cukup menghapus file yang diarahkan oleh storeURL tidak cukup. Anda akan meninggalkan file rekaman eksternal. Karena skema penamaan file rekaman eksternal ini bukan untuk publik, saya belum memiliki solusi universal. - dan 8 Mei '12 pada pukul 23:00

Groundhog
sumber
1
Ini mungkin solusi terbaik untuk keandalan. Jika saya ingin menghapus beberapa tetapi tidak semua data, saya akan menggunakan ini: stackoverflow.com/questions/1077810/…
Michael Grinich
12
Saya tahu cara mengambil dengan benar storeCoordinator. Namun saya tidak tahu bagaimana cara mendapatkan persistentStore. Jadi bisakah Anda memberikan contoh yang tepat dan bukan hanya: NSPersistentStore * store = ...;
Pascal Klein
11
[[NSFileManager defaultManager] removeItemAtURL: storeURL error: & error] lebih baik.
AN0
3
@ Pascal Jika Anda bisa mendapatkan koordinator toko maka Anda memiliki akses ke semua toko gigih melalui properti persistentStores.
Mihai Damian
2
Contoh kode termasuk cara membuat ulang toko kosong baru di sini: stackoverflow.com/a/8467628
Joshua C. Lerner
140

Anda dapat menghapus file SQLite - tetapi saya memilih untuk melakukannya dengan membersihkan tabel satu per satu dengan fungsi:

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

}

Alasan saya memilih untuk melakukan itu tabel demi tabel adalah karena hal itu membuat saya mengkonfirmasi karena saya melakukan pemrograman yang menghapus isi tabel itu masuk akal dan tidak ada data yang lebih baik saya simpan.

Melakukan ini akan jauh lebih lambat daripada hanya menghapus file dan saya akan berubah menjadi penghapusan file jika saya metode ini terlalu lama.

Grouchal
sumber
Solusi bagus Terima kasih. Apa itu DLog ()?
Michael Grinich
Ah ya - maaf itu adalah fungsi khusus yang saya gunakan yang hanya melakukan NSLog ketika build adalah DEBUG build - cukup ganti dengan NSLog.
Grouchal
6
Anda dapat melihat implementasi DLog di sini: cimgf.com/2009/01/24/dropping-nslog-in-release-builds
Matt Long
3
Ini bekerja dengan baik untuk saya. Tetapi untuk membuatnya lebih cepat, adakah cara untuk menghapus semua objek dari entitas tertentu dengan satu perintah? Seperti dalam SQL Anda dapat melakukan sesuatu seperti, DROP TABLE entity_name. Saya tidak ingin menghapus seluruh file SQL karena saya hanya ingin menghapus semua objek dari entitas tertentu, bukan entitas lain.
ma11hew28
8
Gunakan NSDictionary * allEntities = _managedObjectModel.entitiesByName; untuk mendapatkan semua entitas dalam model Anda dan kemudian Anda dapat mengulangi kunci di NSDictionary ini untuk membersihkan semua entitas di toko.
adam0101
60

Solusi yang Diperbarui untuk iOS 10+

Gunakan NSBatchDeleteRequestuntuk menghapus semua objek dalam entitas tanpa harus memuatnya ke dalam memori atau mengulanginya.

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

Kode ini telah diperbarui untuk iOS 10 dan Swift 3. Jika Anda perlu mendukung iOS 9, lihat pertanyaan ini .

Sumber:

Suragch
sumber
3
Saya akan menempatkan bahwa seluruh blok di dalam moc.performBlockAndWait({ () -> Void in... }).
SwiftArchitect
2
Pastikan Anda melihat Mengapa entri tidak dihapus sampai aplikasi dimulai ulang atau saya menjalankan NSBatchDeleteRequest saya dua kali? Panjang cerita kode di atas TIDAK cukup jika entitas dimuat ke dalam memori
Honey
38

Saya telah menulis clearStoresmetode yang melewati setiap toko dan menghapusnya baik dari koordinator dan sistem file (penanganan kesalahan dikesampingkan):

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;

Metode ini ada di dalam coreDataHelperkelas yang menangani (antara lain) menciptakan persistentStore saat nihil.

samvermette
sumber
"tidak ada metode kelas yang dikenal untuk pemilih 'persistentStores'"
Aviram Netanel
27

Saya menghapus semua data dari data inti pada Acara tombol di kelas HomeViewController: Artikel ini sangat membantu saya, saya pikir saya akan berkontribusi.

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

}

Perhatikan bahwa untuk memanggil self.persistentStoreCoordinator saya mendeklarasikan properti di Home View Controller. (Jangan khawatir tentang conto managedObjectContext yang saya gunakan untuk menyimpan dan memuat.)

@property (nonatomic, retain) NSManagedObjectContext        *   managedObjectContext;
@property (nonatomic, retain) NSPersistentStoreCoordinator  *   persistentStoreCoordinator;

Kemudian di AppDelegate ApplicationDidFinishLaunching tepat di bawah ini membuat HomeViewController yang saya miliki:

homeViewController = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
homeViewController.managedObjectContext = self.managedObjectContext;
homeViewController.persistentStoreCoordinator = self.persistentStoreCoordinator;
atreat
sumber
@ayteat, apakah ini berhasil untuk Anda? bagi saya ini tidak berfungsi, silakan lihat di stackoverflow.com/questions/14646595/…
Ranjit
1
INI ADALAH JAWABANNYA, kecuali gunakan "AppDelegate * ad = [[UIApplication sharedApplication] delegate];" dan ganti diri dengan iklan. dan jangan salin dua bit kode terakhir
Cescy
1
Mengapa Anda tidak memanggil reset pada managedObjectContext? Bagaimana jika Anda memiliki referensi kuat ke managedObject?
Parag Bafna
@ ParagBafna Anda benar, contoh kode di atas mengasumsikan bahwa tidak ada referensi yang kuat untuk objek yang dikelola. Jika Anda memiliki beberapa, Anda harus melihat memanggil 'reset' pada managedObjectContext dan menghapus referensi objek yang dikelola yang Anda miliki.
atreat
Hai, terima kasih. Juga, apakah ada cara untuk melakukan ini pada peningkatan aplikasi? Lebih tepatnya, persyaratan saya adalah ketika saya meluncurkan versi aplikasi kami berikutnya, saat itu ketika pengguna memperbarui aplikasi mereka dari appStore, data inti dan file sqlite harus dihapus dan diinisialisasi ulang menjadi kosong. Saya menemukan cara untuk mendeteksi acara peluncuran aplikasi pertama menggunakan nilai Bool di NSUserDefaults dan memeriksa nilai ini di didfinishLaunchingWithOptions oleh delegasi aplikasi, tetapi tidak mengerti cara menghapus semua hal ini. Karena tidak ada tombol dan delegasi aplikasi tidak mendeteksi "persistentStore" saya untuk menghapusnya seperti yang Anda lakukan di atas. ada Bantuan?
Tejas
19

MagicalRecord membuat ini sangat mudah.

[MyCoreDataObject MR_truncateAll];
Brian King
sumber
16
ini keren, tapi di luar topik karena saya menentukan solusi CoreData
Michael Grinich
8
Pengambilan Rekaman Aktif adalah solusi data inti.
casademora
7
Tetapi jawaban seperti ini melampaui ruang lingkup pertanyaan. Tidak ada alasan untuk menganggap dia ingin menggunakan kerangka kerja addt'l untuk melakukan ini.
jpswain
Saya berpendapat bahwa ini tidak menjawab pertanyaan. Ini adalah cara yang baik untuk menghapus entri dari satu entitas, tidak semua entitas ...! Bagaimana Anda menghitung semua entitas dalam model dan mengirimkannya MR_truncateAll?
fatuhoku
Lihat sumber untuk MR_truncateAll - ini mengambil semua objek tetapi bukan propertinya (karena kami bermaksud membuang NSMO), lalu beralih ke objek untuk entitas yang ditentukan dan menghapusnya. github.com/magicalpanda/MagicalRecord/blob/master/MagicalRecord/…
1in9ui5t
19

iOS9 +, Swift 2

Hapus semua objek di semua entitas

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)
        }
    }
}
Andres Wang
sumber
1
Pastikan Anda melihat Mengapa entri tidak dihapus sampai aplikasi dimulai ulang atau saya menjalankan NSBatchDeleteRequest saya dua kali? Cerita panjang kode di atas TIDAK cukup jika entitas dimuat ke dalam memori
Honey
13

[Terlambat menjawab sebagai balasan atas karunia yang meminta tanggapan yang lebih baru]

Melihat jawaban sebelumnya,

  • Mengambil dan menghapus semua item, seperti yang disarankan oleh @Grouchal dan lainnya, masih merupakan solusi yang efektif dan berguna. Jika Anda memiliki penyimpanan data yang sangat besar maka mungkin lambat, tetapi masih berfungsi dengan baik.
  • Menghapus data store saja, seperti yang Anda dan @groundhog catat, tidak lagi efektif. Ini usang bahkan jika Anda tidak menggunakan penyimpanan biner eksternal karena iOS 7 menggunakan mode WAL untuk penjurnalan SQLite. Dengan mode WAL mungkin ada (berpotensi besar) file jurnal yang ada di sekitar untuk penyimpanan persisten Data Inti.

Tetapi ada pendekatan berbeda yang serupa untuk menghapus toko persisten yang berfungsi. Kuncinya adalah menempatkan file toko tetap Anda di sub-direktori sendiri yang tidak mengandung hal lain. Jangan hanya menempelkannya di direktori dokumen (atau di mana pun), buatlah sub-direktori baru hanya untuk toko persisten. Isi direktori itu pada akhirnya akan menjadi file store persisten, file jurnal, dan file biner eksternal. Jika Anda ingin menghapus seluruh penyimpanan data, hapus direktori itu dan semuanya akan hilang.

Anda akan melakukan sesuatu seperti ini ketika menyiapkan toko tetap Anda:

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

Lalu ketika Anda ingin menghapus toko,

[[NSFileManager defaultManager] removeItemAtURL:storeDirectoryURL error:nil];

Itu secara rekursif menghapus sub-direktori kustom dan semua file Core Data di dalamnya.

Ini hanya berfungsi jika Anda belum memiliki toko tetap di folder yang sama dengan data penting lainnya . Seperti direktori dokumen, yang mungkin memiliki hal-hal berguna lainnya di dalamnya. Jika itu situasi Anda, Anda bisa mendapatkan efek yang sama dengan mencari file yang Anda lakukan ingin menyimpan dan menghapus segala sesuatu yang lain. Sesuatu seperti:

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

Pendekatan ini mungkin rawan kesalahan . Anda harus benar-benar yakin bahwa Anda tahu setiap file yang ingin Anda simpan, karena jika tidak, Anda dapat menghapus data penting. Di sisi lain, Anda dapat menghapus file biner eksternal tanpa benar-benar mengetahui nama file / direktori yang digunakan untuk menyimpannya.

Tom Harrington
sumber
jika Anda takut dengan file wal, cukup nonaktifkan
onmyway133
11

Berikut ini adalah solusi gabungan untuk membersihkan Data Inti.

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

Jika Anda ingin menghapus semua objek dan tidak ingin menghapus file pendukung, Anda dapat menggunakan metode berikut:

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

Hati-hati karena mungkin sangat lambat (tergantung pada berapa banyak objek dalam grafik objek Anda).

Marián Černý
sumber
cara menghapus data yang lebih lama (katakan tiga tabel, dari satu tabel saya ingin menghapus data) ketika pembaruan aplikasi
Madan Mohan
6

Jika Anda ingin pergi menghapus rute semua objek (yang jauh lebih sederhana daripada menghancurkan tumpukan Data Core, tetapi lebih sedikit performan), daripada ini adalah implementasi yang lebih baik:

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

Implementasi ini memanfaatkan NSOperationuntuk melakukan penghapusan dari utas utama dan memberi tahu setelah selesai. Anda mungkin ingin memancarkan pemberitahuan atau sesuatu dalam blok penyelesaian untuk menggelembungkan status kembali ke utas utama.

Blake Watters
sumber
Perhatikan bahwa NSManagedObjectContext Anda harus diinisialisasi seperti NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];untuk menggunakan metode ini atau Anda akan mendapatkan kesalahan:Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
Akankah
6

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

Iterasi melalui semua entitas data inti dan bersihkan mereka

KVISH
sumber
4

Terima kasih untuk kirimannya. Saya mengikutinya dan itu berhasil untuk saya. Tapi saya punya masalah lain yang tidak disebutkan dalam balasan. Jadi saya tidak yakin apakah itu hanya saya.

Ngomong-ngomong, saya pikir saya akan memposting masalah di sini dan cara saya menyelesaikannya.

Saya punya beberapa catatan di database, saya ingin membersihkan semuanya bersih sebelum menulis data baru ke db, jadi saya melakukan semuanya termasuk

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

dan kemudian digunakan managedObjectContextuntuk mengakses database (seharusnya sudah kosong sekarang), entah bagaimana datanya masih ada. Setelah beberapa saat pemecahan masalah, saya menemukan bahwa saya harus mengatur ulang managedObjectContext, managedObject, managedObjectModeldan persistentStoreCoordinator, sebelum saya menggunakan managedObjectContextuntuk mengakses dabase tersebut. Sekarang saya memiliki database yang bersih untuk menulis.

DanielZ
sumber
Jadi mengatur ulang managedObjectContext, managedObject, managedObjectModel dan persistentStoreCoordinator menempatkan file yang berisi database kembali setelah dihapus?
Daniel Brower
4

Ini adalah versi yang agak disederhanakan dengan lebih sedikit panggilan ke AppDelegate sendiri dan sedikit kode terakhir yang ditinggalkan dari jawaban berperingkat teratas. Juga saya mendapatkan kesalahan "Toko gigih objek tidak dapat dijangkau dari koordinator NSManagedObjectContext ini" jadi hanya perlu menambahkan itu kembali.

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];
}
Alberto Lopez
sumber
4

solusi cepat:

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)
    }
János
sumber
For swift 2let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "momd")!
Saorikido
3

Sebagai referensi cepat untuk menyimpan pencarian di tempat lain - membuat ulang toko persistent setelah menghapusnya dapat dilakukan dengan:

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
TimD
sumber
Saya mencoba kode Anda, tetapi xcode melempar pengecualian pada baris ini, Jadi apa yang Anda katakan tentang ini.
Ranjit
3

Beberapa jawaban bagus untuk pertanyaan ini. Inilah yang ringkas dan bagus. Dua baris pertama menghapus database sqlite. Kemudian loop for: menghapus semua objek dalam memori 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];
}
adamek
sumber
1
Jangan menyalahgunakan delegasi untuk tujuan ini: hollance.com/2012/02/dont-abuse-the-app-delegate
Michael Dorner
1
Saya setuju dengan @MichaelDorner. Menambahkan banyak ke dalam AppDelegate dapat memengaruhi kinerja dan mengasapi ukuran biner Anda dengan sarang laba-laba yang saling terhubung di mana AppDelegate tiba-tiba perlu dimasukkan dalam setiap kelas. Jika Anda menemukan ini memotong, buat pengontrol terpisah khusus untuk tujuan ini. AppDelegate harus tetap untuk inisialisasi dasar dan menangani perubahan status dalam aplikasi, tidak lebih.
jcpennypincher
2

Anda juga dapat menemukan semua nama entitas, dan menghapusnya dengan nama. Ini versi yang lebih lama tetapi berfungsi dengan baik, dengan begitu Anda tidak harus bekerja dengan toko kegigihan

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

untuk "Any_Entity_Name" berikan saja salah satu dari nama entitas Anda, kami hanya perlu mengetahui deskripsi entitas yang ada di dalam entitas Anda. ValueForKey @ "name" akan mengembalikan semua nama entitas. Akhirnya, jangan lupa untuk menabung.

Chris Lin
sumber
2

Jawaban yang diterima benar dengan menghapus URL oleh NSFileManager benar, tetapi sebagaimana dinyatakan dalam iOS 5+ edit, toko persisten tidak hanya diwakili oleh satu file. Untuk toko SQLite itu * .sqlite, * .sqlite-shm dan * .sqlite-wal ... untungnya karena iOS 7+ kita bisa menggunakan metode

[NSPersistentStoreCoordinator + hapusUbiquitousContentAndPersistentStoreAtURL: options: error:]

untuk mengurus penghapusan, jadi kodenya harus seperti ini:

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];
JakubKnejzlik
sumber
2
Anda harus melewati dict opsi, khususnya nama toko, misalnya: @ {NSPersistentStoreUbiquitousContentNameKey: @ "MyData"};
tomi44g
2

Berikut adalah versi yang menghapus setiap catatan di setiap tabel yang Anda miliki.

Cepat 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)")
    }
}
Politta
sumber
2

Swift 4/5, iOS 9+

Membangun kembali seluruh CoreDatafile SQLite akan memastikan semua data terhapus, oleh karena itu semua entitas dihapus. Panggil saja 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()
    }
}
J. Doe
sumber
untuk siapa pun yang menggunakan ini, harap dicatat bahwa itu hanya akan crash "pertama kali" ketika tidak ada file sql di sana (saya hanya menggunakan "penjaga" dalam jawaban saya)
Fattie
1

Bekerja dengan semua versi. Lulus nama entitas dan ulangi untuk menghapus semua entri dan menyimpan konteks.

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)")
    }
}
Karun Kumar
sumber
1

Satu metode lain (terlepas dari permintaan penghapusan batch) yang sering saya gunakan (berdasarkan persyaratan aplikasi) adalah untuk mereset toko persisten. Implementasinya terlihat seperti ini untuk iOS 10+ dan Swift (dengan asumsi Anda memiliki kelas 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)
        }
    }

}

Satu keuntungan dari metode ini adalah lebih mudah terutama ketika Anda memiliki banyak catatan data untuk banyak entitas dalam data inti Anda. Dalam hal ini permintaan batch yang dihapus akan memakan banyak memori.

Oluwatobi Omotayo
sumber
1

Solusi 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)
    }
}
Charlton Provatas
sumber
0

Hapus file toko terus-menerus dan siapkan koordinator toko tetap baru?

Pemburu
sumber
6
Untungnya, melakukan pembersihan tidak akan menghapus file toko yang persisten. Itu akan menjadi resep bencana jika benar.
Hunter
0

Hapus sqlite dari fileURLPath Anda dan kemudian buat.

Jai
sumber
Maksud saya ketika aplikasi diinstal.
Michael Grinich
0

Dengan asumsi Anda menggunakan MagicalRecorddan memiliki toko persistensi default:

Saya tidak suka semua solusi yang menganggap file tertentu ada dan / atau permintaan memasukkan nama entitas atau kelas. Ini adalah Swift (2), cara aman untuk menghapus semua data dari semua entitas. Setelah menghapus itu akan membuat ulang tumpukan baru juga (saya sebenarnya tidak yakin bagaimana perlunya bagian ini).

Ini godo untuk situasi gaya "logout" ketika Anda ingin menghapus semuanya tetapi memiliki toko yang berfungsi dan moc untuk mendapatkan data baru (setelah pengguna login ...)

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

    }
}
Aviel Gross
sumber
0

Gunakan ini

+(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];
}
Sandeep Singh
sumber
0

Saya mengambil kode Grouchal dan untuk mempercepatnya saya menggunakan enumerasi dengan mode bersamaan ( NSEnumerationConcurrent), itu menjadi sedikit lebih cepat dibandingkan dengan untuk loop (di aplikasi saya, saya menambahkan fitur ini untuk Penguji sehingga mereka dapat menghapus data dan melakukan testcases daripada menghapus dan instal aplikasi)

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

di sini versi swift3 saya untuk menghapus semua catatan. 'Pengguna' adalah nama entitas

@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
    }   
}
Kursat Turkay
sumber