핵심 데이터를 사용하여 웹 서비스 호출의 결과를 로컬로 유지하고 있습니다. 웹 서비스는 “Cars”에 대해 전체 객체 모델을 반환합니다. “Cars”는 약 2000 개가 될 수 있습니다 (웹 서비스가 1 개 또는 모든 자동차보다 작은 값을 반환하도록 할 수는 없습니다).
다음에 응용 프로그램을 열 때 모든 자동차에 대해 웹 서비스를 다시 호출하여 Core Data 지속 복사본을 새로 고치려고하지만 중복을 방지하려면 먼저 로컬 캐시의 모든 데이터를 제거해야합니다.
관리 객체 컨텍스트 (예 : “CAR”유형의 모든 엔터티)에서 특정 엔터티의 모든 인스턴스를 제거하는 더 빠른 방법이 있습니까? 아니면 쿼리를 호출 한 다음 결과를 반복하여 각 인스턴스를 삭제 한 다음 저장해야합니까?
이상적으로 엔티티가 Blah 인 모든 것을 삭제한다고 말할 수 있습니다.
답변
iOS 9 이상 :
iOS 9 NSBatchDeleteRequest
에는 술어와 일치하는 객체를 모두 메모리에로드하지 않고도 쉽게 삭제할 수 있는 새로운 클래스가 추가되었습니다 . 사용 방법은 다음과 같습니다.
스위프트 5
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Car")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try myPersistentStoreCoordinator.execute(deleteRequest, with: myContext)
} catch let error as NSError {
// TODO: handle the error
}
목표 -C
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
NSError *deleteError = nil;
[myPersistentStoreCoordinator executeRequest:delete withContext:myContext error:&deleteError];
배치 삭제에 대한 자세한 내용은 WWDC 2015의 “핵심 데이터의 새로운 기능”세션 (~ 14 : 10에서 시작)에서 확인할 수 있습니다.
iOS 8 이하 :
모두 가져 오기 및 모두 삭제 :
NSFetchRequest *allCars = [[NSFetchRequest alloc] init];
[allCars setEntity:[NSEntityDescription entityForName:@"Car" inManagedObjectContext:myContext]];
[allCars setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError *error = nil;
NSArray *cars = [myContext executeFetchRequest:allCars error:&error];
[allCars release];
//error handling goes here
for (NSManagedObject *car in cars) {
[myContext deleteObject:car];
}
NSError *saveError = nil;
[myContext save:&saveError];
//more error handling here
답변
Swift 3 에서 엔티티 재설정 :
func resetAllRecords(in entity : String) // entity = Your_Entity_Name
{
let context = ( UIApplication.shared.delegate as! AppDelegate ).persistentContainer.viewContext
let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
do
{
try context.execute(deleteRequest)
try context.save()
}
catch
{
print ("There was an error")
}
}
답변
조금 더 깨끗하고 보편적 인 방법 :이 방법을 추가하십시오 :
- (void)deleteAllEntities:(NSString *)nameEntity
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:nameEntity];
[fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError *error;
NSArray *fetchedObjects = [theContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *object in fetchedObjects)
{
[theContext deleteObject:object];
}
error = nil;
[theContext save:&error];
}
답변
스위프트 2.0 :
class func clearCoreData(entity:String) {
let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName(entity, inManagedObjectContext: moc!)
fetchRequest.includesPropertyValues = false
do {
if let results = try moc!.executeFetchRequest(fetchRequest) as? [NSManagedObject] {
for result in results {
moc!.deleteObject(result)
}
try moc!.save()
}
} catch {
LOG.debug("failed to clear core data")
}
}
답변
빠른:
let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
fetchRequest.includesPropertyValues = false
var error:NSError?
if let results = context.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject] {
for result in results {
context.deleteObject(result)
}
var error:NSError?
if context.save(&error) {
// do something after save
} else if let error = error {
println(error.userInfo)
}
} else if let error = error {
println("error: \(error)")
}
답변
이것은 하나에 비슷한 질문입니다 여기에 누군가 당신이 하나의 개체를 삭제해야하므로 관계 삭제 규칙을 설정 제안했다. 따라서 자동차와 많은 관계가있는 엔터티를 가지고 있거나 만들 수 있고 더 높은 엔터티를 삭제할 때 삭제 규칙을 계단식으로 설정하면 모든 자동차도 삭제됩니다. 모든 차량 적재와 관련된 단계를 수행 할 필요가 없으므로 처리 시간이 절약 될 수 있습니다. 더 큰 데이터 세트에서는 이것이 절대적으로 필요할 수 있습니다.
답변
좋은 답변이 이미 게시되었습니다. 이것은 추천 일뿐입니다!
좋은 방법은 카테고리를 추가하고 NSManagedObject
내가 한 것처럼 메소드를 구현하는 것입니다.
헤더 파일 (예를 들어 NSManagedObject+Ext.h
)
@interface NSManagedObject (Logic)
+ (void) deleteAllFromEntity:(NSString*) entityName;
@end
코드 파일 : (예 : NSManagedObject + Ext.m)
@implementation NSManagedObject (Logic)
+ (void) deleteAllFromEntity:(NSString *)entityName {
NSManagedObjectContext *managedObjectContext = [AppDelegate managedObjectContext];
NSFetchRequest * allRecords = [[NSFetchRequest alloc] init];
[allRecords setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext]];
[allRecords setIncludesPropertyValues:NO];
NSError * error = nil;
NSArray * result = [managedObjectContext executeFetchRequest:allRecords error:&error];
for (NSManagedObject * profile in result) {
[managedObjectContext deleteObject:profile];
}
NSError *saveError = nil;
[managedObjectContext save:&saveError];
}
@end
… 당신이해야 할 유일한 것은 app delegate에서 managedObjectContext를 가져 오는 것입니다.
나중에 다음과 같이 사용할 수 있습니다.
[NSManagedObject deleteAllFromEntity:@"EntityName"];
하나의 추가 최적화는 tha entityname에 대한 매개 변수를 제거하고 clazzname에서 대신 이름을 얻는 것입니다. 이것은 사용법으로 이어질 것입니다 :
[ClazzName deleteAllFromEntity];
보다 깨끗한 impl (NSManagedObjectContext의 카테고리로) :
@implementation NSManagedObjectContext (Logic)
- (void) deleteAllFromEntity:(NSString *)entityName {
NSFetchRequest * allRecords = [[NSFetchRequest alloc] init];
[allRecords setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:self]];
[allRecords setIncludesPropertyValues:NO];
NSError * error = nil;
NSArray * result = [self executeFetchRequest:allRecords error:&error];
for (NSManagedObject * profile in result) {
[self deleteObject:profile];
}
NSError *saveError = nil;
[self save:&saveError];
}
@end
그런 다음 사용법 :
[managedObjectContext deleteAllFromEntity:@"EntityName"];