Temel Verilerdeki tüm girişler silinsin / sıfırlansın mı?


235

Temel Veriler'de depolanan tüm girdileri silmenin bir yolunu biliyor musunuz? Şemam aynı kalmalı; Sadece boş olarak sıfırlamak istiyorum.


Düzenle

Bir kullanıcı aslında bir resetdüğmeye basmak böylece bunu programlı olarak yapmak için arıyorum .


6
Aşağıdaki cevapların çoğu tarihli. Kullanın NSBatchDeleteRequest. stackoverflow.com/a/31961330/3681880
Suragch

Yanıtlar:


198

Yine de NSFileManager: removeItemAtPath :: yöntemini kullanarak dosyayı programlı olarak silebilirsiniz.

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

Ardından, düzgün bir şekilde yeniden oluşturulduğundan emin olmak için kalıcı mağazayı geri ekleyin.

Her varlık üzerinden yineleme yapmanın programlı yolu hem daha yavaş hem de hataya yatkındır. Bunu bu şekilde kullanmanın amacı, bazı varlıkları silmek, diğerlerini silmek istemenizdir. Ancak, yine de referans bütünlüğünü koruduğunuzdan emin olmanız gerekir, aksi takdirde değişikliklerinizi devam ettiremezsiniz.

Mağazayı kaldırmak ve yeniden oluşturmak hem hızlı hem de güvenlidir ve kesinlikle çalışma zamanında programlanabilir.

İOS5 + için güncelleme

İOS 5 ve OS X 10.7'de harici ikili depolamanın (harici kayıt dosyasında ExExBBDataDataStorage veya Store'a izin verir) piyasaya sürülmesiyle, storeURL'lerin işaret ettiği dosyaları silmek yeterli değildir. Harici kayıt dosyalarını geride bırakacaksınız. Bu harici kayıt dosyalarının adlandırma düzeni herkese açık olmadığından henüz evrensel bir çözümüm yok. - an0 8 Mayıs '23 at 23:00


1
Bu muhtemelen güvenilirlik için en iyi çözümdür. Tüm verileri değil ama bazı verileri silmek isteseydim, şunu kullanırdım: stackoverflow.com/questions/1077810/…
Michael Grinich

12
StoreCoordinator'ı düzgün bir şekilde nasıl alacağımı biliyorum. Ancak persistentStore almak için nasıl bilmiyorum. Öyleyse sadece yerine uygun bir örnek verebilir misiniz: NSPersistentStore * store = ...;
Pascal Klein

11
[[NSFileManager defaultManager] removeItemAtURL: storeURL hatası: & error] daha iyi.
an0

3
@Pascal Mağaza koordinatörünü alabiliyorsanız, persistentStores özelliği aracılığıyla tüm kalıcı mağazalarına erişebilirsiniz.
Mihai Damian

2
Burada yeni bir boş mağazanın nasıl yeniden oluşturulacağını içeren örnek kod: stackoverflow.com/a/8467628
Joshua C. Lerner

140

SQLite dosyasını silebilirsiniz - ancak tabloları bir işlevle ayrı ayrı temizleyerek yapmayı seçiyorum:

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

}

Tabloyu tabloya göre yapmamın nedeni, tablonun içeriğini silmenin mantıklı olduğunu ve saklamak istediğim veri olmadığını programlama yaparken onaylamamı sağlıyor.

Bunu yapmak sadece dosyayı silmekten çok daha yavaş olacaktır ve eğer bu yöntem çok uzun sürerse bir dosya silme işlemine geçeceğim.


Harika bir çözüm. Teşekkürler. DLog () nedir?
Michael Grinich

Ah evet - üzgünüm, sadece bir yapı bir DEBUG yapı olduğunda bir NSLog yapan özel bir işlevdir - sadece NSLog ile değiştirin.
Grouchal

6
DLog'un bir uygulamasını burada görebilirsiniz: cimgf.com/2009/01/24/dropping-nslog-in-release-builds
Matt Long

3
Bu benim için iyi çalışıyor. Ancak daha hızlı gitmek için, belirli bir varlığın tüm nesnelerini tek bir komutla silmenin bir yolu var mı? SQL'de olduğu gibi, DROP TABLE varlık_adı gibi bir şey yapabilirsiniz. Tüm SQL dosyasını silmek istemiyorum çünkü yalnızca belirli bir varlığın tüm nesnelerini silmek istiyorum, diğer varlıkları değil.
ma11hew28

8
NSDictionary * kullanın allEntities = _managedObjectModel.entitiesByName; modelinizdeki tüm varlıkları almak ve daha sonra mağazadaki tüm varlıkları temizlemek için bu NSDictionary'deki tuşları tekrarlayabilirsiniz.
adam0101

60

İOS 10+ için Güncellenmiş Çözüm

NSBatchDeleteRequestVarlıktaki tüm nesneleri belleğe yüklemek veya yinelemek zorunda kalmadan silmek için kullanın .

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

Bu kod iOS 10 ve Swift 3 için güncellendi. İOS 9'u desteklemeniz gerekiyorsa, bu soruya bakın .

Kaynaklar:


3
Tüm bloğu bir moc.performBlockAndWait({ () -> Void in... içine yerleştirirdim }).
SwiftArchitect

2
Uygulama yeniden başlatılıncaya veya NSBatchDeleteRequest'imi iki kez yürütene kadar girişlerin neden silinmediğini gördüğünüzden emin olun. Uzun hikaye Yukarıdaki kod yeterli değildir eğer kişiler belleğe yüklenir
Bal

38

clearStoresHer mağazadan geçen ve hem koordinatörden hem de dosya sisteminden silinen bir yöntem yazdım (hata işleme bir kenara bırakıldı):

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;

Bu yöntem, coreDataHelper(diğer şeylerin yanı sıra) nil olduğunda persistentStore oluşturmaya özen gösteren bir sınıfın içindedir .


"seçici 'persistentStores' için bilinen bir sınıf yöntemi yok"
Aviram Netanel

27

Bir düğme üzerindeki temel verilerden tüm verileri HomeViewController sınıfındaki olaydan kaldırırım: Bu makale bana katkıda bulunacağımı düşündüm.

-(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 öğesini çağırmak için Home View Controller'da bir özellik beyan ettiğimi unutmayın. (Kaydetme ve yükleme için kullandığım manageObjectContext hakkında endişelenmeyin.)

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

Sonra hemen bir HomeViewController oluşturma AppDelegate ApplicationDidFinishLaunching içinde ben var:

homeViewController = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
homeViewController.managedObjectContext = self.managedObjectContext;
homeViewController.persistentStoreCoordinator = self.persistentStoreCoordinator;

@ayteat, bu işe yaradı mı? benim için çalışmıyor, lütfen şu stackoverflow.com/questions/14646595/…
Ranjit

1
"AppDelegate * ad = [[UIApplication sharedApplication] delegate];" kullanımı dışında CEVAPTIR. ve kendini reklamla değiştir. ve kodun son iki
parçasını

1
Neden manageObjectContext üzerinde reset çağırmıyorsunuz? YönetilenObject'e güçlü bir referansınız varsa ne olur?
Parag Bafna

@ParagBafna Doğru, yukarıdaki kod örneği yönetilen nesnelere güçlü bir başvuru olmadığını varsayar. Bazılarınız varsa, yönetilenObjectContext üzerinde 'reset' çağrısına bakmalı ve sahip olduğunuz yönetilen nesnelerin referanslarını kaldırmalısınız.
atreat

Hey teşekkürler. Ayrıca, uygulama güncellemesinde bunu yapmanın bir yolu var mı? Kesin olmak gerekirse, gereksinimim bir sonraki uygulama sürümümüzü yuvarladığım zaman, kullanıcı app uygulamasını AppStore'dan güncellediğinde, temel veri n sqlite dosyaları silinmeli ve boş olarak yeniden başlatılmalıdır. NSUserDefaults'ta bir Bool değeri kullanarak uygulamanın ilk başlatma olayını tespit etmenin ve uygulama temsilcisinin didfinishLaunchingWithOptions'ta bu değeri kontrol etmenin yolunu anladım, ancak bunların nasıl temizleneceğini anlayamadım. Hiçbir düğme ve uygulama temsilcisi, yukarıda yaptığınız gibi temizlemek için "persistentStore" algılamıyor olduğundan. herhangi bir yardım?
Tejas

19

MagicalRecord bunu çok kolaylaştırıyor.

[MyCoreDataObject MR_truncateAll];

16
Bu serin, ama bir CoreData çözüm belirtildi çünkü konu kapalı
Michael Grinich

8
Active kayıt getiriliyor olduğu bir çekirdek veri çözeltisi.
casademora

7
Ancak böyle bir cevap sorunun kapsamının ötesine geçer. Bunu yapmak için ek bir çerçeve kullanmak istediğini varsaymak için hiçbir neden yoktur.
jpswain

Bunun soruyu cevaplamadığını iddia ediyorum. Bu, tüm varlıklardan değil, tek bir varlıktan girdileri kaldırmak için iyi bir yoldur ...! Modeldeki tüm varlıkları nasıl numaralandırır ve gönderirsiniz MR_truncateAll?
fatuhoku

MR_truncateAll kaynağını görüntüleyin - tüm nesneleri getirir, ancak özelliklerini almaz (NSMO'ları atmayı düşündüğümüz gibi), daha sonra belirtilen varlık için nesnelerin üzerinden yinelenir ve bunları siler. github.com/magicalpanda/MagicalRecord/blob/master/MagicalRecord/…
1in9ui5t

19

iOS9 +, Swift 2

Tüm varlıklardaki tüm nesneleri sil

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
Uygulama yeniden başlatılıncaya veya NSBatchDeleteRequest'imi iki kez yürütene kadar girişlerin neden silinmediğini gördüğünüzden emin olun. Uzun hikaye Yukarıdaki kod yeterli değildir eğer kişiler belleğe yüklenir
Bal

13

[Daha yeni yanıtlar isteyen bir lütuf karşısında geç cevap]

Önceki cevaplara baktığımızda,

  • @Grouchal ve diğerleri tarafından önerildiği gibi, tüm öğeleri getirmek ve silmek hala etkili ve kullanışlı bir çözümdür. Çok büyük veri depolarınız varsa, yavaş olabilir, ancak yine de çok iyi çalışır.
  • Siz ve @groundhog'un not ettiği gibi, veri deposunu kaldırmak artık etkili değildir. Harici ikili depolama birimi kullanmasanız bile geçersizdir, çünkü iOS 7 SQLite günlük kaydı için WAL modunu kullanır. WAL modunda, herhangi bir Çekirdek Veri kalıcı deposu için (muhtemelen büyük) günlük dosyaları olabilir.

Ancak, işe yarayan kalıcı mağazayı kaldırmak için farklı, benzer bir yaklaşım var. Anahtar, kalıcı mağaza dosyanızı başka bir şey içermeyen kendi alt dizinine koymaktır. Yalnızca belge dizinine (veya herhangi bir yere) yapıştırmayın, yalnızca kalıcı mağaza için yeni bir alt dizin oluşturun. Bu dizinin içeriği kalıcı saklama dosyası, günlük dosyaları ve harici ikili dosyalar olur. Tüm veri deposunu tıklatmak istiyorsanız, bu dizini silin, hepsi kaybolur.

Kalıcı mağazanızı kurarken böyle bir şey yaparsınız:

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

Sonra mağazayı kaldırmak istediğinizde,

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

Bu, hem özel alt dizini hem de içindeki tüm Temel Veri dosyalarını yinelemeli olarak kaldırır.

Bu yalnızca kalıcı deponuzu diğer önemli verilerle aynı klasörde yoksa çalışır . Muhtemelen içinde başka yararlı şeyler olan belgeler dizini gibi. Bu senin durum varsa, o dosyalara bakarak aynı etkiyi alabilir do tutmak istiyoruz ve her şeyi kaldırarak. Gibi bir şey:

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

Bu yaklaşım hataya meyilli olabilir . Saklamak istediğiniz her dosyayı bildiğinizden kesinlikle emin olmalısınız , aksi takdirde önemli verileri kaldırabilirsiniz. Öte yandan, harici ikili dosyaları saklamak için kullanılan dosya / dizin adını gerçekten bilmeden kaldırabilirsiniz.


wal dosyasından korkuyorsanız, sadece devre dışı bırakın
onmyway133

11

İşte Temel Verileri temizlemek için kombine çözüm.

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

Tüm nesneleri silmek ve yedekleme dosyalarını silmek istemiyorsanız, aşağıdaki yöntemleri kullanabilirsiniz:

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

Çok yavaş olabileceğine dikkat edin (nesne grafiğinizde kaç nesne olduğuna bağlıdır).


Uygulama güncellemeleri sırasında eski verileri (üç tablo, bir tablodan veri silmek istiyorum) kaldırma
Madan Mohan

6

Tüm nesneleri silme yoluna gitmek istiyorsanız (Çekirdek Veri yığınını yıkmaktan çok daha basit, ancak daha az performans), bu daha iyi bir uygulamadır:

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

Bu uygulama NSOperation, ana iş parçacığının silinmesini gerçekleştirmek ve tamamlandığında bilgilendirmek için kullanılır. Durumu ana iş parçacığına geri döndürmek için tamamlama bloğunda bir bildirim veya başka bir şey yayınlamak isteyebilirsiniz.


Senin NSManagedObjectContext gibi başlatılmalıdır Not NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];Bu yöntemi kullanmak için illâ hatayı alıyorum:Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
Will

6

iOS 10 + Swift 3 çözümü:

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

Tüm temel veri varlıkları üzerinden yinelenir ve bunları temizler


4

Gönderi için teşekkürler. Onu takip ettim ve benim için çalıştı. Ama cevapların hiçbirinde bahsedilmeyen başka bir sorunum vardı. Bu yüzden sadece ben olup olmadığımdan emin değilim.

Her neyse, burada sorunu ve çözüm yolumu göndereceğimi düşündüm.

Ben veritabanında birkaç kayıt vardı, ben db yeni veri yazmadan önce her şeyi temiz temizlemek istedim, bu yüzden dahil her şeyi yaptım

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

ve daha sonra managedObjectContextveritabanına erişmek için kullanılır (şimdiye kadar boş olması gerekiyordu), bir şekilde veriler hala oradaydı. Sorun giderme Bir süre sonra ben sıfırlamak gerekir bulundu managedObjectContext, managedObject, managedObjectModelve persistentStoreCoordinatorben kullanmadan önce, managedObjectContextdabase erişmek için. Şimdi yazmak için temiz bir veritabanı var.


Yani manageObjectContext, manageObject, manageObjectModel ve persistentStoreCoordinator sıfırlandığında, veritabanını içeren dosyayı silindikten sonra geri koyar?
Daniel Brower

4

İşte AppDelegate'in kendine daha az çağrı ve en yüksek puanlı yanıtın dışında kalan son kod bitiyle biraz basitleştirilmiş bir sürüm. Ayrıca "Nesne kalıcı mağaza bu NSManagedObjectContext koordinatörü ulaşılabilir değildir" bir hata alıyordu bu yüzden sadece geri eklemek için gerekli.

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

hızlı çözüm:

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

Hızlı 2 içinlet modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "momd")!
Saorikido

3

Başka bir yerde aramayı kaydetmek için hızlı bir referans olarak - kalıcı mağazayı sildikten sonra yeniden oluşturmak aşağıdakilerle yapılabilir:

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

Kodunuzu denedim, ancak xcode bu satırda bir istisna atar, Peki bu konuda ne söylemelisiniz.
Ranjit

3

Bu soruya birkaç iyi cevap. İşte güzel bir özlü. İlk iki satır sqlite veritabanını siler. Ardından for: döngüsü, yönetilenObjectContext belleğindeki nesneleri siler.

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
Delegasyonu bu amaçla kötüye kullanmayın: hollance.com/2012/02/dont-abuse-the-app-delegate
Michael Dorner

1
@MichaelDorner ile hemfikirim. AppDelegate'e çok şey eklemek, performansı etkileyebilir ve AppDelegate'in aniden her sınıfa dahil edilmesi gereken birbirine bağlı bir bağımlılık örümcek ağı ile ikili dosya boyutunuzu şişirebilir. Bu kırpmayı bulursanız, bu amaca özel ayrı bir denetleyici oluşturun. AppDelegate, uygulamadaki temel başlatma ve işleme durumu değişikliklerine yönelik olarak kalmalıdır, daha fazla değil.
jcpennypincher

2

ayrıca tüm varlık adlarını bulabilir ve ada göre silebilirsiniz. Daha uzun bir versiyon ama iyi çalışıyor, bu şekilde kalıcılık deposu ile çalışmak zorunda değilsiniz

 - (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" için yalnızca kuruluşunuzun adlarından herhangi birini verin, yalnızca varlıklarınızın içerisindeki varlık açıklamasını bulmamız gerekir. ValueForKey @ "name" tüm varlık adlarını döndürür. Son olarak, kaydetmeyi unutmayın.


2

Kabul edilen cevap, URL'nin NSFileManager tarafından kaldırılmasıyla doğrudur, ancak iOS 5+ düzenlemesinde belirtildiği gibi, kalıcı mağaza yalnızca bir dosyayla temsil edilmez. SQLite mağazası için * .sqlite, * .sqlite-shm ve * .sqlite-wal ... neyse ki iOS 7+'den beri yöntemi kullanabiliriz

[NSPersistentStoreCoordinator + removeUbiquitousContentAndPersistentStoreAtURL: seçenekler: hata:]

kaldırmaya dikkat etmek için, kod böyle bir şey olmalıdır:

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
Seçenekler dict'i, özellikle mağaza adını, örneğin: @ {NSPersistentStoreUbiquitousContentNameKey: @ "MyData"};
tomi44g

2

İşte sahip olduğunuz her tablodaki her kaydı silen bir sürüm.

Hızlı 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+

Tüm CoreDataSQLite dosyasını yeniden oluşturmak, tüm verilerin silinmesini sağlar, bu nedenle tüm varlıklar silinir. Sadece ara 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()
    }
}

Bunu kullanan herkes için, orada hiçbir sql dosyası olmadığında sadece "ilk kez"
çökecektir unutmayın

1

Tüm sürümlerle çalışır. Varlık adını iletin ve tüm girişleri silmek ve içeriği kaydetmek için tekrarlayın.

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

Sıklıkla kullandığım (uygulama gereksinimine göre) diğer bir yöntem (silme toplu isteği dışında) kalıcı depoyu sıfırlamaktır. Uygulama iOS 10+ ve Swift için aşağıdaki gibi görünüyor (bir CoreDataManager sınıfınız olduğunu varsayarak):

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

}

Bu yöntemin bir avantajı, özellikle temel verilerinizdeki çok sayıda varlık için çok fazla veri kaydınız olduğunda daha basit olmasıdır. Bu durumda, bir toplu iş silme isteği bellek yoğun olur.


1

Swift 5.1 Çözümü

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

Kalıcı mağaza dosyasını silmek ve yeni bir kalıcı mağaza koordinatörü kurmak?


6
Temizlik yapmak kalıcı depo dosyalarını neyse ki kaldırmaz. Bu doğruysa felaket için bir reçete olurdu.
Hunter

0

Sqlite dosyasını ururpath dosyasından silin ve sonra derleyin.


Uygulama yüklendiğinde demek istedim.
Michael Grinich

0

MagicalRecordVarsayılan bir kalıcılık deposu kullandığınızı ve varsayalım:

Belirli dosyaların var olduğunu ve / veya varlıkların adlarını veya sınıflarını girmeyi talep eden tüm çözümleri sevmiyorum. Bu, tüm varlıklardan tüm verileri silmenin hızlı ve güvenli bir yoludur. Sildikten sonra da taze bir yığın oluşturacak (aslında bu bölümün ne kadar gerekli olduğundan emin değilim).

Her şeyi silmek istediğinizde, ancak yeni bir veri almak için çalışan bir mağazaya ve moc'a sahip olduğunuzda (kullanıcı oturum açtığında ...) "çıkış" tarzı durumlar için godo.

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

Bunu kullan

+(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'ın kodunu aldım ve hızlandırmak için eşzamanlı modla numaralandırma kullandım ( NSEnumerationConcurrent), döngü için karşılaştırıldığında biraz daha hızlı oldu (uygulamamda Test için bu özelliği ekledim, böylece verileri silebilir ve silebilirler. uygulamayı yükle)

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

Burada tüm kayıtları silmek için swift3 sürümüm. 'Kullanıcılar' varlık adıdır

@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
    }   
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.