핵심 데이터의 모든 항목을 삭제 / 재설정 하시겠습니까?


235

Core Data에 저장된 모든 항목을 삭제하는 방법을 알고 있습니까? 내 스키마는 동일하게 유지되어야합니다. 그냥 공백으로 재설정하고 싶습니다.


편집하다

사용자가 기본적으로 reset버튼을 누를 수 있도록 프로그래밍 방식 으로이 작업을 수행하려고 합니다.


6
아래의 많은 답변은 날짜가 있습니다. 사용하십시오 NSBatchDeleteRequest. stackoverflow.com/a/31961330/3681880
Suragch

답변:


198

NSFileManager : removeItemAtPath :: 메소드를 사용하여 프로그래밍 방식으로 파일을 삭제할 수 있습니다.

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

그런 다음 지속적 저장소를 다시 추가하여 올바르게 다시 작성하십시오.

각 엔티티를 반복하는 프로그래밍 방식은 느리고 오류가 발생하기 쉽습니다. 그런 식으로 사용하는 것은 다른 엔티티가 아닌 일부 엔티티를 삭제하려는 경우입니다. 그러나 여전히 참조 무결성을 유지해야합니다. 그렇지 않으면 변경 사항을 유지할 수 없습니다.

상점을 제거하고 다시 작성하면 빠르고 안전하며 런타임에 프로그래밍 방식으로 수행 할 수 있습니다.

iOS5 이상 업데이트

iOS 5 및 OS X 10.7에 외부 바이너리 저장소 (ExternalBinaryDataStorage 또는 외부 레코드 파일에 저장)를 도입하면 storeURL이 가리키는 파일을 삭제하는 것만으로는 충분하지 않습니다. 외부 레코드 파일은 그대로 둡니다. 이러한 외부 레코드 파일의 이름 지정 체계는 공개적이지 않으므로 아직 보편적 인 솔루션이 없습니다. – an0 5 월 8 일 12시 23:00


1
이것은 아마도 최고의 안정성 솔루션입니다. : 좀 있지만 모든 데이터를 삭제하고자한다면, 나는이 사용하는 것이 stackoverflow.com/questions/1077810/...
마이클 Grinich

12
storeCoordinator를 올바르게 검색하는 방법을 알고 있습니다. 그러나 permanentStore를 얻는 방법을 모르겠습니다. NSPersistentStore * store = ...; 대신 적절한 예제를 제시해 주시겠습니까?
파스칼 클라인

11
[[NSFileManager defaultManager] removeItemAtURL : storeURL 오류 : & error]가 좋습니다.
an0

3
@Pascal 만약 당신이 상점 코디네이터를 얻을 수 있다면, 그러면 여러분은 persistStores 속성을 통해 모든 영구 상점에 접근 할 수 있습니다.
Mihai Damian 2019

2
: 여기에 새로운 빈 저장소를 다시하는 방법을 포함하여 예제 코드 stackoverflow.com/a/8467628
여호수아 C. 러너

140

SQLite 파일을 삭제할 수는 있지만 함수를 사용하여 테이블을 개별적으로 제거하여 선택합니다.

- (void) deleteAllObjects: (NSString *) entityDescription  {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityDescription inManagedObjectContext:_managedObjectContext];
    [fetchRequest setEntity:entity];

    NSError *error;
    NSArray *items = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];


    for (NSManagedObject *managedObject in items) {
        [_managedObjectContext deleteObject:managedObject];
        DLog(@"%@ object deleted",entityDescription);
    }
    if (![_managedObjectContext save:&error]) {
        DLog(@"Error deleting %@ - error:%@",entityDescription,error);
    }

}

내가 테이블별로 테이블을 선택하는 이유는 프로그래밍을 수행하면서 테이블의 내용을 삭제하는 것이 합리적이며 오히려 유지할 데이터가 없다는 것을 확인하게하기 때문입니다.

이렇게하면 파일을 삭제하는 것보다 훨씬 느리며이 방법이 너무 오래 걸리면 파일 삭제로 변경됩니다.


훌륭한 솔루션. 감사. DLog () 란 무엇입니까?
Michael Grinich

아 네-죄송합니다. 빌드가 DEBUG 빌드 일 때 NSLog 만 수행하는 특수 함수입니다 .NSLog로 바꾸십시오.
Grouchal

6
여기에서 DLog 구현을 볼 수 있습니다. cimgf.com/2009/01/24/dropping-nslog-in-release-builds
Matt Long

3
이것은 나에게 잘 작동합니다. 그러나 더 빠르게하기 위해 하나의 명령으로 특정 엔티티의 모든 객체를 삭제할 수 있습니까? SQL에서와 같이 DROP TABLE entity_name과 같은 작업을 수행 할 수 있습니다. 다른 엔터티가 아닌 특정 엔터티의 모든 개체 만 삭제하기 때문에 전체 SQL 파일을 삭제하고 싶지 않습니다.
ma11hew28

8
NSDictionary 사용 * allEntities = _managedObjectModel.entitiesByName; 모델의 모든 엔티티를 가져 오면이 NSDictionary의 키를 반복하여 상점의 모든 엔티티를 제거 할 수 있습니다.
adam0101

60

iOS 10 이상을위한 업데이트 된 솔루션

사용 NSBatchDeleteRequest그들을 통해 메모리 또는 반복 처리에로드 할 필요없이 기업의 모든 개체를 삭제합니다.

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

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

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

이 코드는 iOS 10 및 Swift 3 용으로 업데이트되었습니다. iOS 9를 지원해야하는 경우이 질문을 참조하십시오 .

출처 :


3
나는 그 전체 블록을 moc.performBlockAndWait({ () -> Void in... 안에 넣을 것이다 }).
SwiftArchitect

2
앱을 다시 시작하거나 NSBatchDeleteRequest를 두 번 실행할 때까지 왜 항목이 삭제되지 않는지 확인하십시오 . 엔터티가 메모리에로드 되면 위의 코드로는 충분하지 않습니다
Honey

38

clearStores모든 저장소를 거치고 코디네이터와 파일 시스템에서 모두 삭제 하는 방법을 작성했습니다 (오류 처리는 제외).

NSArray *stores = [persistentStoreCoordinator persistentStores];

for(NSPersistentStore *store in stores) {
    [persistentStoreCoordinator removePersistentStore:store error:nil];
    [[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
}

[persistentStoreCoordinator release], persistentStoreCoordinator = nil;

이 메소드는 coreDataHelper클래스가 없을 때 영속 저장소를 작성하는 것을 처리합니다.


"선택기 'persistentStores'에 대해 알려진 클래스 방법이 없습니다"
Aviram Netanel

27

HomeViewController 클래스의 버튼 이벤트에서 핵심 데이터에서 모든 데이터를 제거합니다.이 기사는 내가 기여할 것이라고 생각했습니다.

-(IBAction)buttonReset:(id)sender
{
    NSLog(@"buttonReset Pressed");

    //Erase the persistent store from coordinator and also file manager.
    NSPersistentStore *store = [self.persistentStoreCoordinator.persistentStores lastObject];
    NSError *error = nil;
    NSURL *storeURL = store.URL;
    [self.persistentStoreCoordinator removePersistentStore:store error:&error];
    [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];


    NSLog(@"Data Reset");

    //Make new persistent store for future saves   (Taken From Above Answer)
    if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        // do something with the error
    }

}

self.persistentStoreCoordinator를 호출하기 위해 홈 뷰 컨트롤러에서 속성을 선언했습니다. (저장 및로드에 사용하는 managedObjectContext에 대해 걱정하지 마십시오.)

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

그런 다음 AppDelegate ApplicationDidFinishLaunching에서 HomeViewController를 생성하는 바로 아래에 있습니다.

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

@ayteat, 이것이 당신을 위해 일했습니까?. 나를 위해 작동하지 않는,이 stackoverflow.com/questions/14646595/…를
Ranjit

1
"AppDelegate * ad = [[UIApplication sharedApplication] delegate];"사용을 제외하고는 대답입니다. 자기를 광고로 바꿉니다. 마지막 두 비트의 코드를 복사하지
마십시오

1
managedObjectContext에서 reset을 호출하지 않는 이유는 무엇입니까? managedObject에 대한 강력한 참조가 있으면 어떻게합니까?
Parag Bafna

@ParagBafna 위의 코드 샘플은 관리 객체에 대한 강력한 참조가 없다고 가정합니다. 일부가있는 경우 managedObjectContext에서 'reset'을 호출하고 가지고있는 모든 관리 객체를 역 참조해야합니다.
atreat

고마워 또한 앱 업그레이드 에서이 작업을 수행 할 수있는 방법이 있습니까? 정확히 말하면, 내 요구 사항은 다음 버전의 앱을 롤링 할 때, 사용자가 appStore에서 앱을 업데이트 할 때 핵심 데이터 n sqlite 파일을 삭제하고 다시 초기화해야합니다. NSUserDefaults에서 Bool 값을 사용하고 앱 대리자의 didfinishLaunchingWithOptions 에서이 값을 확인하여 앱 첫 실행 이벤트를 감지하는 방법을 알아 냈지만이 모든 것을 지우는 방법을 이해하지 못했습니다. 버튼이 없으며 앱 대리자가 위의 "persistentStore"를 감지하지 않아서 위와 같이 지 웠습니다. 어떤 도움?
Tejas

19

MagicalRecord 는 이것을 매우 쉽게 만듭니다.

[MyCoreDataObject MR_truncateAll];

16
이 멋진이지만, 주제와 나는 CoreData 솔루션 지정된 이후
마이클 Grinich

8
Active Record Fetching 핵심 데이터 솔루션입니다.
casademora

7
그러나 이와 같은 대답은 질문의 범위를 벗어납니다. 그가이를 위해 추가 프레임 워크를 사용한다고 가정 할 이유가 없습니다.
jpswain

나는 이것이 질문에 대답하지 않는다고 주장한다. 이것은 모든 엔티티가 아닌 하나의 엔티티에서 항목을 제거하는 좋은 방법입니다 ...! 모델의 모든 엔티티를 어떻게 열거하고 전송 MR_truncateAll합니까?
fatuhoku

MR_truncateAll의 소스를 봅니다. NSMO를 삭제하려는 것처럼 모든 객체를 가져오고 속성은 가져 오지 않고 지정된 엔티티의 객체를 반복하여 삭제합니다. github.com/magicalpanda/MagicalRecord/blob/master/MagicalRecord/…
1in9ui5t

19

iOS9 +, 스위프트 2

모든 엔티티에서 모든 객체 삭제

func clearCoreDataStore() {
    let entities = managedObjectModel.entities
    for entity in entities {
        let fetchRequest = NSFetchRequest(entityName: entity.name!)
        let deleteReqest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
        do {
            try context.executeRequest(deleteReqest)
        } catch {
            print(error)
        }
    }
}

1
앱을 다시 시작하거나 NSBatchDeleteRequest를 두 번 실행할 때까지 왜 항목이 삭제되지 않는지 확인하십시오 . 엔터티가 메모리에로드 되면 위의 코드로는 충분하지 않습니다
Honey

13

[새로운 답변을 요구하는 현상금에 대한 답변으로 늦게 답변]

이전 답변을 살펴보면

  • @Grouchal 및 기타에서 제안한대로 모든 항목을 가져오고 삭제하는 것은 여전히 ​​효과적이고 유용한 솔루션입니다. 매우 큰 데이터 저장소가있는 경우 속도가 느릴 수 있지만 여전히 잘 작동합니다.
  • @groundhog와 마찬가지로 데이터 저장소를 제거하는 것만으로는 더 이상 효과적이지 않습니다. 그것은 오래된의 외부 바이너리 스토리지를 사용하지 않는 경우에도 SQLite는 iOS의 7 사용 WAL 모드가 저널링 때문이다. WAL 모드를 사용하면 Core Data 영구 저장소에 대해 잠재적으로 큰 저널 파일이있을 수 있습니다.

그러나 작동하는 영구 저장소를 제거하는 다른 유사한 접근 방식이 있습니다. 핵심은 영구 저장소 파일을 다른 것을 포함하지 않는 자체 하위 디렉토리에 저장하는 것입니다. 문서 디렉토리 (또는 어디에서나)에 넣지 말고 영구 저장소에 대해서만 새 서브 디렉토리를 작성하십시오. 해당 디렉토리의 내용은 영구 저장소 파일, 저널 파일 및 외부 2 진 파일이됩니다. 전체 데이터 저장소를 정리하려면 해당 디렉토리를 삭제하면 모두 사라집니다.

영구 저장소를 설정할 때 다음과 같은 작업을 수행하십시오.

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

이 방법은 오류가 발생하기 쉽습니다 . 보관하고 싶은 모든 파일을 알고 있어야 합니다. 그렇지 않으면 중요한 데이터가 제거 될 수 있습니다. 반면에 외부 바이너리 파일은 실제로 저장하는 데 사용 된 파일 / 디렉토리 이름을 몰라도 제거 할 수 있습니다.


wal 파일이 두려운 경우에는 비활성화하십시오
onmyway133

11

다음은 Core Data를 제거하기위한 통합 솔루션입니다.

- (void)deleteAllObjectsInCoreData
{
    NSArray *allEntities = self.managedObjectModel.entities;
    for (NSEntityDescription *entityDescription in allEntities)
    {
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        [fetchRequest setEntity:entityDescription];

        fetchRequest.includesPropertyValues = NO;
        fetchRequest.includesSubentities = NO;

        NSError *error;
        NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

        if (error) {
                NSLog(@"Error requesting items from Core Data: %@", [error localizedDescription]);
            }

        for (NSManagedObject *managedObject in items) {
            [self.managedObjectContext deleteObject:managedObject];
        }

        if (![self.managedObjectContext save:&error]) {
            NSLog(@"Error deleting %@ - error:%@", entityDescription, [error localizedDescription]);
        }
    }  
}

10

모든 객체를 삭제하고 백업 파일을 삭제하지 않으려는 경우 다음 방법을 사용할 수 있습니다.

- (void)deleteAllObjectsInContext:(NSManagedObjectContext *)context
                       usingModel:(NSManagedObjectModel *)model
{
    NSArray *entities = model.entities;
    for (NSEntityDescription *entityDescription in entities) {
        [self deleteAllObjectsWithEntityName:entityDescription.name
                                   inContext:context];
    }
}

- (void)deleteAllObjectsWithEntityName:(NSString *)entityName
                             inContext:(NSManagedObjectContext *)context
{
    NSFetchRequest *fetchRequest =
        [NSFetchRequest fetchRequestWithEntityName:entityName];
    fetchRequest.includesPropertyValues = NO;
    fetchRequest.includesSubentities = NO;

    NSError *error;
    NSArray *items = [context executeFetchRequest:fetchRequest error:&error];

    for (NSManagedObject *managedObject in items) {
        [context deleteObject:managedObject];
        NSLog(@"Deleted %@", entityName);
    }
}

속도가 매우 느릴 수 있습니다 (오브젝트 그래프에있는 오브젝트 수에 따라 다름).


앱 업데이트시 이전 데이터를 제거하는 방법 (예 : 하나의 테이블에서 세 개의 테이블, 데이터를 지우고 싶습니다)
Madan Mohan

6

모든 객체 삭제 라우트를 이동하려면 (핵심 데이터 스택을 분해하는 것보다 훨씬 간단하지만 성능이 떨어지는)보다 나은 구현입니다.

- (void)deleteAllManagedObjectsInModel:(NSManagedObjectModel *)managedObjectModel context:(NSManagedObjectContext *)managedObjectContext
{
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        [managedObjectContext performBlockAndWait:^{
            for (NSEntityDescription *entity in managedObjectModel) {
                NSFetchRequest *fetchRequest = [NSFetchRequest new];
                [fetchRequest setEntity:entity];
                [fetchRequest setIncludesSubentities:NO];
                NSArray *objects = [managedObjectContext executeFetchRequest:fetchRequest error:nil];
                for (NSManagedObject *managedObject in objects) {
                    [managedObjectContext deleteObject:managedObject];
                }            
            }

            [managedObjectContext save:nil];
        }];
    }];
    [operation setCompletionBlock:^{
        // Do stuff once the truncation is complete
    }];
    [operation start];
}

이 구현은 NSOperation기본 스레드에서 삭제를 수행하고 완료시 알립니다. 완료 블록 내에서 알림을 보내거나 상태를 메인 스레드로 다시 버블 링 할 수 있습니다.


NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];이 메소드를 사용하려면 NSManagedObjectContext를 초기화해야합니다. 그렇지 않으면 오류가 발생합니다.Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
Will

6

iOS 10 + Swift 3 솔루션 :

func clearCoreDataStore() {
    let delegate = UIApplication.shared.delegate as! AppDelegate
    let context = delegate.persistentContainer.viewContext

    for i in 0...delegate.persistentContainer.managedObjectModel.entities.count-1 {
        let entity = delegate.persistentContainer.managedObjectModel.entities[i]

        do {
            let query = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
            let deleterequest = NSBatchDeleteRequest(fetchRequest: query)
            try context.execute(deleterequest)
            try context.save()

        } catch let error as NSError {
            print("Error: \(error.localizedDescription)")
            abort()
        }
    }
}

모든 핵심 데이터 엔터티를 반복하고 지 웁니다.


4

게시물 주셔서 감사합니다. 나는 그것을 따라 갔고 그것은 나를 위해 일했다. 그러나 나는 어떤 대답에서도 언급되지 않은 또 다른 문제가있었습니다. 그래서 그것이 단지 나인지 확실하지 않습니다.

어쨌든, 내가 여기에 문제와 그 해결 방법을 게시 할 것이라고 생각했습니다.

데이터베이스에 몇 가지 레코드가 있었으므로 새 데이터를 db에 쓰기 전에 모든 것을 정리하고 싶었습니다.

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

그런 다음 managedObjectContext데이터베이스에 액세스하는 데 사용 되었습니다 (지금까지는 비어 있음). 어쨌든 데이터는 여전히 존재했습니다. 문제 해결 잠시 후, 나는 다시 할 필요가 있음을 발견 managedObjectContext, managedObject, managedObjectModel그리고 persistentStoreCoordinator내가 사용하기 전에, managedObjectContextdabase에 액세스 할 수 있습니다. 이제 쓸 데이터베이스가 깨끗합니다.


따라서 managedObjectContext, managedObject, managedObjectModel 및 persistStoreCoordinator를 재설정하면 데이터베이스가 포함 된 파일이 삭제 된 후 다시 배치됩니까?
Daniel Brower

4

다음은 AppDelegate 자체에 대한 호출이 적고 최고 등급의 답변에서 제외 된 마지막 코드 비트가있는 다소 단순화 된 버전입니다. 또한 "이 NSManagedObjectContext 코디네이터에서 객체의 영구 저장소에 접근 할 수 없습니다"라는 오류가 발생하여 다시 추가해야했습니다.

NSPersistentStoreCoordinator *storeCoordinator = [self persistentStoreCoordinator];
NSPersistentStore *store = [[storeCoordinator persistentStores] lastObject];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"dataModel"];
NSError *error;

[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];

if (storeCoordinator != nil) {
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:storeCoordinator];
}

4

신속한 솔루션 :

class func deleteAllManagedObjects() {

        let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "mom")
        let mom = NSManagedObjectModel(contentsOfURL: modelURL)

        for entityName in mom.entitiesByName.keys {
            let fr = NSFetchRequest(entityName: entityName as String)
            let a = Utility.managedObjectContext().executeFetchRequest(fr, error: nil) as [NSManagedObject]
            for mo in a {
                Utility.managedObjectContext().deleteObject(mo)
            }
        }

        Utility.managedObjectContext().save(nil)
    }

신속한 2를 위해let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "momd")!
Saorikido

3

다른 곳에서 검색을 저장하는 빠른 참조로 영구 저장소를 삭제 한 후 다시 작성하면 다음을 수행 할 수 있습니다.

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

나는 당신의 코드를 시도했지만 xcode는이 줄에 예외를 던졌습니다. 그래서 당신은 이것에 대해 말해야합니다.
Ranjit

3

이 질문에 대한 몇 가지 좋은 답변. 여기에 간결한 것이 있습니다. 처음 두 줄은 sqlite 데이터베이스를 삭제합니다. 그런 다음 for : 루프는 managedObjectContext 메모리의 모든 객체를 삭제합니다.

NSURL *storeURL = [[(FXYAppDelegate*)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory] URLByAppendingPathComponent:@"AppName.sqlite"];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
for (NSManagedObject *ct in [self.managedObjectContext registeredObjects]) {
    [self.managedObjectContext deleteObject:ct];
}

1
이러한 목적으로 대표단을 남용하지 마십시오. hollance.com/2012/02/dont-abuse-the-app-delegate
Michael Dorner

1
@MichaelDorner에 동의합니다. AppDelegate에 많은 기능을 추가하면 모든 클래스에 AppDelegate가 갑자기 포함되어야하는 상호 연결된 종속 거미줄로 성능에 영향을 미치고 바이너리 크기를 부 풀릴 수 있습니다. 이 문제가 발생하면이 용도에 맞는 별도의 컨트롤러를 만드십시오. AppDelegate는 응용 프로그램의 기본 초기화 및 처리 상태 변경을 유지해야합니다.
jcpennypincher

2

모든 엔터티 이름을 찾아서 이름으로 삭제할 수도 있습니다. 더 긴 버전이지만 잘 작동하므로 지속성 저장소로 작업 할 필요가 없습니다.

 - (void)clearCoreData
{
NSError *error;
NSEntityDescription *des = [NSEntityDescription entityForName:@"Any_Entity_Name" inManagedObjectContext:_managedObjectContext];
NSManagedObjectModel *model = [des managedObjectModel];
NSArray *entityNames = [[model entities] valueForKey:@"name"];

for (NSString *entityName in entityNames){

    NSFetchRequest *deleteAll = [NSFetchRequest fetchRequestWithEntityName:entityName];
    NSArray *matches = [self.database.managedObjectContext executeFetchRequest:deleteAll error:&error];

}
    if (matches.count > 0){
        for (id obj in matches){

            [_managedObjectContext deleteObject:obj];
        }
       [self.database.managedObjectContext save:&error];
    }
}

"Any_Entity_Name"의 경우 엔터티 이름 중 하나만 제공하면 엔터티가 속한 엔터티 설명 만 파악하면됩니다. ValueForKey @ "name"은 모든 엔티티 이름을 리턴합니다. 마지막으로, 저장하는 것을 잊지 마십시오.


2

NSFileManager로 URL을 제거하면 허용되는 대답은 정확하지만 iOS 5 이상 편집에 명시된 것처럼 영구 저장소는 하나의 파일로만 표현되지는 않습니다. SQLite 저장소의 경우 * .sqlite, * .sqlite-shm 및 * .sqlite-wal ... 다행히 iOS 7 이상부터 메소드를 사용할 수 있습니다

[NSPersistentStoreCoordinator + removeUbiquitousContentAndPersistentStoreAtURL : options : error :]

제거를 처리하려면 코드는 다음과 같아야합니다.

NSPersistentStore *store = ...;
NSError *error;
NSURL *storeURL = store.URL;
NSString *storeName = ...;
NSPersistentStoreCoordinator *storeCoordinator = ...;
[storeCoordinator removePersistentStore:store error:&error];
[NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:storeURL.path options:@{NSPersistentStoreUbiquitousContentNameKey: storeName} error:&error];

2
옵션 저장소, 특히 상점 이름을 전달해야합니다. 예 : @ {NSPersistentStoreUbiquitousContentNameKey : @ "MyData"};
tomi44g 2019

2

다음은 모든 테이블의 모든 레코드를 삭제하는 버전입니다.

스위프트 4

static func resetDatabase() {
    do {
        try dataStore.persistentStoreCoordinator.managedObjectModel.entities.forEach { (entity) in
            if let name = entity.name {
                let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: name)
                let request = NSBatchDeleteRequest(fetchRequest: fetch)
                try mainContext.execute(request)
            }
        }

        try mainContext.save()
    } catch {
        print("error resenting the database: \(error.localizedDescription)")
    }
}

2

스위프트 4/5, iOS 9+

전체 CoreDataSQLite 파일을 다시 작성하면 모든 데이터가 지워 지므로 모든 엔티티가 삭제됩니다. 전화 deleteAndRebuild()하세요.

class CoreDataStack {
    // Change this
    static let datamodelName = "ProjectName"
    static let storeType = "sqlite"

    static let persistentContainer = NSPersistentContainer(name: datamodelName)
    private static let url: URL = {
        let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")

        assert(FileManager.default.fileExists(atPath: url.path))

        return url
    }()

    static func loadStores() {
        persistentContainer.loadPersistentStores(completionHandler: { (nsPersistentStoreDescription, error) in
            if let error = error {
                fatalError(error.localizedDescription)
            }
        })
    }

    static func deleteAndRebuild() {
        try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)

        loadStores()
    }
}

가 (난 그냥 내 대답에 "가드"를 사용)에는 SQL 파일이 없을 때이 사용하는 모든 사용자를 들어, 그냥 "처음"충돌 점에 유의을
Fattie

1

모든 버전에서 작동합니다. 엔티티 이름을 전달하고 반복하여 모든 항목을 삭제하고 컨텍스트를 저장하십시오.

func deleteData(entityToFetch: String, completion: @escaping(_ returned: Bool) ->()) {
    var context = NSManagedObjectContext()
    if #available(iOS 10.0, *) {
        context = self.persistentContainer.viewContext
    } else {
        context = self.managedObjectContext
    }

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
    fetchRequest.entity = NSEntityDescription.entity(forEntityName: entityToFetch, in: context)
    fetchRequest.includesPropertyValues = false
    do {
        let results = try context.fetch(fetchRequest) as! [NSManagedObject]
        for result in results {
            context.delete(result)
        }
        try context.save()
        completion(true)
    } catch {
        completion(false)
        print("fetch error -\(error.localizedDescription)")
    }
}

1

내가 자주 사용하는 다른 방법 (배치 삭제 요청 제외) (앱 요구 사항에 따라)은 영구 저장소를 재설정하는 것입니다. 구현은 iOS 10 이상 및 Swift에 대해 다음과 같습니다 (CoreDataManager 클래스가 있다고 가정).

let persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "<Data-Model-Name>“)
    container.loadPersistentStores(completionHandler: { (storeDescription, err) in
        if let err = err {
            fatalError("loading of store failed: \(err)")
        }
    })
    return container
}()

func resetPersistentStore() {

    if let persistentStore = persistentContainer.persistentStoreCoordinator.persistentStores.last {
        let storeURL = persistentContainer.persistentStoreCoordinator.url(for: persistentStore)

        do {
            try persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: storeURL, ofType: NSSQLiteStoreType, options: nil)
        } catch {
            print("failed to destroy persistent store:", error.localizedDescription)
        }

        do {
            try persistentContainer.persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
        } catch {
            print("failed to re-add persistent store:", error.localizedDescription)
        }
    }

}

이 방법의 장점 중 하나는 특히 핵심 데이터의 수많은 엔터티에 대한 많은 데이터 레코드가있을 때 더욱 간단하다는 것입니다. 이 경우 일괄 삭제 요청은 메모리를 많이 사용합니다.


1

스위프트 5.1 솔루션

public static func reset() {
    let coordinator = _persistentContainer.persistentStoreCoordinator
    for store in coordinator.persistentStores where store.url != nil {
        try? coordinator.remove(store)
        try? FileManager.default.removeItem(atPath: store.url!.path)
    }
}

0

영구 저장소 파일을 삭제하고 새 영구 저장소 코디네이터를 설정 하시겠습니까?


6
정리해도 영구 저장소 파일은 제거되지 않습니다. 그것이 사실이라면 재앙의 요리법이 될 것입니다.
Hunter


0

사용 중이고 MagicalRecord기본 지속성 저장소가 있다고 가정합니다 .

특정 파일이 존재한다고 가정하거나 엔티티 이름 또는 클래스를 입력 해야하는 모든 솔루션을 좋아하지 않습니다. 이것은 모든 엔티티에서 모든 데이터를 삭제하는 안전한 방법 인 Swift (2)입니다. 삭제 한 후에도 새로운 스택을 다시 생성합니다 (실제로이 부분이 얼마나 필요한지 확실하지 않습니다).

모든 것을 삭제하고 싶지만 새로운 데이터를 얻기 위해 작업 저장소와 moc를 가지고 싶을 때 "로그 아웃"스타일 상황에 적합합니다.

extension NSManagedObject {

    class func dropAllData() {

        MagicalRecord.saveWithBlock({ context in

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

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

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

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

    }
}

0

이것을 사용하십시오

+(NSArray *)fetchDataFromEntity:(NSString *)entityName context:(NSManagedObjectContext *)context
{
    NSFetchRequest * fetchRequest =[[NSFetchRequest alloc] init];
    NSEntityDescription * CategoriesEntity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    [fetchRequest setEntity:CategoriesEntity];

    NSError * error;
    NSInteger count = [context countForFetchRequest:fetchRequest error:&error];

    if (count && count>0) {

        NSArray * fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
        if (fetchedObjects && fetchedObjects.count>0) {

            return fetchedObjects;
        }else
            return nil;

    }
    else
        return nil;
}
+ (void)deleteObjectsOfArray:(NSMutableArray*)ary context:(NSManagedObjectContext *)context {
    for (NSManagedObject * obj in ary) {
        [context deleteObject:obj];
    }
    NSError *saveError = nil;
    [context save:&saveError];
}
+ (void)deleteEntity:(NSString *)entityName context:(NSManagedObjectContext *)context {
    NSArray *listArray = [self fetchDataFromEntity:entityName context:context];
    [self deleteObjectsOfArray:[NSMutableArray arrayWithArray:listArray] context:context];
}

0

Grouchal의 코드를 가져 와서 속도를 높이기 위해 동시 모드 ( NSEnumerationConcurrent)로 열거 형을 사용 했는데 for 루프와 비교하여 조금 빨랐습니다 (내 응용 프로그램에서 테스터 에이 기능을 추가하여 데이터를 지우고 테스트 케이스를 삭제하지 않고 수행 할 수 있습니다. 앱 설치)

- (void)resetObjects
{
    [self deleteAllObjectsInEntity:@"Entity1"];
    [self deleteAllObjectsInEntity:@"Entity2"];
    [self deleteAllObjectsInEntity:@"Entity3"];
    [self deleteAllObjectsInEntity:@"Entity4"];
}

-(void) deleteAllObjectsInEntity:(NSString*) entityName
{
    MainDataContext *coreDataContext = [MainDataContext sharedInstance];
    NSManagedObjectContext *currentContext = coreDataContext.managedObjectContext;
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:currentContext];
    [fetchRequest setEntity:entity];

    NSError *error;
    NSArray *items = [currentContext executeFetchRequest:fetchRequest error:&error];

    [items enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSManagedObject * obj, NSUInteger idx, BOOL *stop) {
        [currentContext deleteObject:obj];
    }];


    if (![currentContext save:&error]) {
        NSLog(@"Error deleting %@ - error:%@",entityName,error);
    }
}

0

여기 내 모든 swift3 버전은 모든 레코드를 삭제합니다. '사용자'는 엔티티 이름입니다

@IBAction func btnDelAll_touchupinside(_ sender: Any) {

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let managedObjectContext = appDelegate.persistentContainer.viewContext

    let fetchReq = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
    let req = NSBatchDeleteRequest(fetchRequest: fetchReq)

    do {
        try managedObjectContext.execute(req)

    } catch {
        // Error Handling
    }   
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.