iphone - وعلق - حذف/إعادة تعيين جميع الإدخالات في البيانات الأساسية؟




مسح جميع المحتويات والاعدادات في الايفون (20)

هل تعرف بأي طريقة لحذف جميع الإدخالات المخزنة في Core Data؟ يجب أن يبقى المخطط الخاص بي كما هو ؛ أنا فقط أريد إعادة تعيينه على فارغة.

تصحيح

أنا أتطلع إلى القيام بذلك برمجيًا حتى يتمكن المستخدم من الوصول إلى زر reset أساسي.


حل محدث لنظام التشغيل iOS 9+

استخدم NSBatchDeleteRequest لحذف كافة الكائنات في الكيان دون الحاجة إلى تحميلها في الذاكرة أو التكرار من خلالها.

// create the delete request for the specified entity
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "MyEntity")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

// get reference to the persistent container
let persistentContainer = (UIApplication.shared.delegate as! AppDelegate).persistentContainer

// perform the delete
do {
    try persistentContainer.viewContext.execute(deleteRequest)
} catch let error as NSError {
    print(error)
}

تم تحديث هذا الرمز لـ iOS 10 و Swift 3. إذا كنت بحاجة إلى دعم iOS 9 ، فراجع هذا السؤال .

مصادر:


iOS 10 و Swift 3

بافتراض أن اسم الكيان هو "Photo" ، وأنك تقوم بإنشاء فئة CoreDataStack ...

 func clearData() {
        do {            
            let context = CoreDataStack.sharedInstance.persistentContainer.viewContext
            let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Photo")
            do {
                let objects  = try context.fetch(fetchRequest) as? [NSManagedObject]
                _ = objects.map{$0.map{context.delete($0)}}
                CoreDataStack.sharedInstance.saveContext()
            } catch let error {
                print("ERROR DELETING : \(error)")
            }
        }
    }

هنا هو تعليمي جيد لكيفية استخدام CoreData وكيفية استخدام هذه الطريقة. https://medium.com/compileswift/parsing-json-response-and-save-it-in-coredata-step-by-step-fb58fc6ce16f#.1tu6kt8qb


أخذت رمز Grouchal وسرعته أنا استخدم التعداد مع الوضع المتزامن ( NSEnumerationConcurrent ) ، حصلت على أسرع قليلا مقارنة بالحلقة (في تطبيقي أضفت هذه الميزة إلى المختبرين حتى يتمكنوا من مسح البيانات والقيام بالاختبارات بدلا من حذفها وتثبيت التطبيق)

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

أقوم بإزالة جميع البيانات من البيانات الأساسية على زر حدث في فصل 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. (لا تقلق بشأن manageObjectContext الذي أستخدمه للحفظ والتحميل.)

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

إذا كنت تريد أن تسلك الطريق حذف جميع الكائنات (وهو أبسط بكثير من تمزيق مكدس البيانات الأساسية ، ولكن أقل أداء) ، من هذا هو تنفيذ أفضل:

- (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 لتنفيذ عملية حذف الخيط الرئيسي وإعلامه عند الانتهاء. قد ترغب في إصدار إشعار أو شيء ما داخل كتلة الإكمال لإعادة الفقاعة إلى الحالة السابقة إلى سلسلة المحادثات الرئيسية.


إذا كنت تريد حذف جميع الكائنات ولا تريد حذف ملفات النسخ الاحتياطي ، فيمكنك استخدام الطرق التالية:

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

احذر من أنه قد يكون بطيئًا جدًا (يعتمد على عدد الكائنات الموجودة في الرسم البياني الكائن).


إليك إصدار يحذف كل سجل في كل جدول لديك.

سويفت 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)")
    }
}

استخدم هذا

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

بافتراض أنك تستخدم MagicalRecord ولديك مخزن استمرارية افتراضي:

لا أحب جميع الحلول التي تفترض وجود ملفات معينة و / أو المطالبة بإدخال أسماء أو فئات الكيانات. هذه طريقة سويفت (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)
        }

    }
}

حذف sqlite من ملف yourURLLPath ثم بناء.


حل سريع:

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

شكرا لهذا المنصب. تابعت ذلك وعملت لي. لكن لدي مشكلة أخرى لم يتم ذكرها في أي من الردود. ﻟذا ، ﻟﺳت ﻣﺗﺄﻛدًا ﻣﻣﺎ إذا ﻛﺎن ﻟﻲ ﻓﻘط.

على أي حال ، أعتقد أنني سأقوم بنشر المشكلة هنا وطريقي التي حلت ذلك.

كان لدي بعض السجلات في قاعدة البيانات ، أردت تطهير كل شيء نظيفًا قبل كتابة بيانات جديدة إلى db ، لذلك فعلت كل شيء بما في ذلك

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

ثم استخدم managedObjectContext للوصول إلى قاعدة البيانات (من المفترض أن تكون فارغة الآن) ، بطريقة ما كانت البيانات لا تزال موجودة. بعد فترة من تحرّي الخلل وإصلاحه ، اكتشفت أنني بحاجة إلى إعادة ضبط managedObjectContext و managedObject و managedObjectModel و persistentStoreCoordinator ، قبل أن أستخدم managedObjectContext للوصول إلى dabase. الآن لدي قاعدة بيانات نظيفة للكتابة عليها.


كمرجع سريع لحفظ البحث في مكان آخر - يمكن إعادة إنشاء المتجر الدائم بعد حذفه من خلال:

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the 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 الذي يعتني (من بين أشياء أخرى) إنشاء persistentStore عندما لا يكون.


هل تريد حذف ملف المتجر الدائم وإعداد منسق متجر مستمر جديد؟


هنا إصدار 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
    }   
}

يعمل مع جميع الإصدارات. قم بتمرير اسم الكيان ثم قم بالتكرار لحذف جميع المدخلات وحفظ السياق.

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

يمكنك أيضًا العثور على جميع أسماء الكيانات وحذفها حسب الاسم. لها نسخة أطول ولكن يعمل بشكل جيد ، وبهذه الطريقة لم يكن لديك للعمل مع مخزن استمرار

 - (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" بكافة أسماء الكيانات. وأخيرًا ، لا تنسَ الحفظ.


MagicalRecord يجعل هذا سهل للغاية.

[MyCoreDataObject MR_truncateAll];

[إجابة متأخرة ردا على فضل يطلب استجابات أحدث]

تبحث على إجابات سابقة ،

  • لا يزال جلب جميع العناصر وحذفها ، كما اقترح من قبلGrouchal وغيرها ، يمثل حلاً فعالاً ومفيدًا. إذا كان لديك مخازن بيانات كبيرة جدًا ، فقد تكون بطيئة ، ولكنها لا تزال تعمل جيدًا.
  • ببساطة إزالة مخزن البيانات ، كما كنت وgroundhog ملاحظة ، لم تعد فعالة. إنه عفا عليه الزمن حتى إذا كنت لا تستخدم تخزينًا ثنائيًا خارجيًا لأن iOS 7 يستخدم وضع WAL لـ journalling SQLite. مع وضع WAL ، قد تكون هناك ملفات يومية (كبيرة الحجم) موجودة حول أي مخزن دائم للبيانات الأساسية.

ولكن هناك طريقة مشابهة ومتشابهة لإزالة المخزن الدائم الذي يعمل. المفتاح هو وضع ملف مخزن متواصل في دليل فرعي خاص به لا يحتوي على أي شيء آخر. لا تقم فقط بتثبيته في دليل المستندات (أو في أي مكان) ، قم بإنشاء دليل فرعي جديد لمخزن دائم. ستنتهي محتويات هذا الدليل إلى ملف التخزين الدائم ، وملفات دفتر اليومية ، والملفات الثنائية الخارجية. إذا كنت تريد تخزين مخزن البيانات بالكامل ، فاحذف هذا الدليل وسيختفي جميعًا.

ستفعل شيئًا كهذا عند إعداد متجرك المستمر:

NSURL *storeDirectoryURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"persistent-store"];
if ([[NSFileManager defaultManager] createDirectoryAtURL:storeDirectoryURL
        withIntermediateDirectories:NO
        attributes:nil
        error:nil]) {
    NSURL *storeURL = [storeDirectoryURL URLByAppendingPathComponent:@"MyApp.sqlite"];
    // continue with storeURL as usual...
}

ثم عندما أردت إزالة المتجر ،

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

يقوم ذلك بشكل متكرر بإزالة كل من الدليل الفرعي المخصص وكافة ملفات البيانات الأساسية الموجودة فيه.

يعمل هذا فقط إذا لم يكن لديك بالفعل مخزن دائم في نفس المجلد مثل البيانات الهامة الأخرى . مثل دليل المستندات ، والذي ربما يحتوي على أشياء أخرى مفيدة فيه. إذا كان هذا هو موقفك ، يمكنك الحصول على نفس التأثير من خلال البحث عن الملفات التي تريد الاحتفاظ بها وإزالة أي شيء آخر. شيء مثل:

NSString *docsDirectoryPath = [[self applicationDocumentsDirectory] path];
NSArray *docsDirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:docsDirectoryPath error:nil];
for (NSString *docsDirectoryItem in docsDirectoryContents) {
    // Look at docsDirectoryItem. If it's something you want to keep, do nothing.
    // If it's something you don't recognize, remove it.
}

قد يكون هذا النهج عرضة للخطأ . يجب أن تكون متأكدًا تمامًا من أنك تعرف كل ملف تريد الاحتفاظ به ، وإلا فقد تزيل بيانات مهمة. على الجانب الآخر ، يمكنك إزالة الملفات الثنائية الخارجية دون معرفة اسم الملف / الدليل المستخدم لتخزينها.





core-data