从特定部分删除核心数据对象 [英] Deleting core data objects from a specific section

查看:86
本文介绍了从特定部分删除核心数据对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常奇怪的问题,但如果我能解释得很好,我想答案不会那么困难。
这是我当前的场景:



我有一个有六个固定段的tableView。



部分填充了核心数据对象。



我使用一个transient属性来决定对象必须显示在哪个部分。此过程在NSManagedObject子类中完成。临时属性称为 sectionIdentifier



由于使用临时属性来决定哪个节出现每个对象,我决定在每个部分创建一个特殊的行,意图每个部分至少有一行。这个选项会减少问题,有一个nil部分,在添加或删除行时会抛出异常,至少这是一个问题有时在测试应用程序时。



这意味着在第一次启动每个部分都有一行(我将称为特殊行)。然后用户可以完全添加/删除行。



我现在的问题是,如果该部分有新行,我需要删除这个特殊的行。同时,如果用户删除部分中的最后一行,应用程序会自动创建一个新的特殊行,因此该部分永远不为空。



我知道这不是管理它的最好的方法,但是由于我的iOS知识,这是我发现避免异常,从空部分添加或删除行的最好的方法。



我需要的是,当用户向节添加至少一个新行时,从节中删除该特殊行。



对象具有名为 quitar 的字符串属性,以及特殊行: quitar = @si。这样,所有特殊行都很容易识别。



我使用此代码删除特殊行,如果在部分有新行:

  NSManagedObjectContext * context = self.managedObjectContext; 

NSEntityDescription * entity = [NSEntityDescription entityForName:@ToDoIteminManagedObjectContext:context];
NSFetchRequest * fetch = [[NSFetchRequest alloc] init];
[fetch setEntity:entity];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@quitar like'si'];
[fetch setPredicate:predicate];
NSError * fetchError;
NSArray * fetchedData = [self.managedObjectContext executeFetchRequest:fetch error:& fetchError];
for(NSManagedObject * item in fetchedData){

[context deleteObject:item];
}

我被告知您不能在 NSPredicate ,您可以在我的代码中看到所有特殊行都被删除,不仅是所需部分的特殊行。
我需要你的帮助,找到一个方法,只从我想要的部分,而不是从所有的部分删除特殊的行。



谢谢你,对不起



请在下面找到我在中指定sectionIdentifier的方式。 NSManagedObject class ToDoItem

   - NSString *)sectionIdentifier {

[self willAccessValueForKey:@sectionIdentifier];
NSString * tmp = [self primitiveValueForKey:@sectionIdentifier];
[self didAccessValueForKey:@sectionIdentifier];




if(!tmp){


NSCalendar * calendar = [NSCalendar currentCalendar];
NSInteger comps =(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);

NSDate * today = [NSDate date];
NSDate * date = self.todoDueDate;

NSDateComponents * components = [[NSDateComponents alloc] init];
[components setCalendar:calendar];
[components setYear:2065];
[components setMonth:11];
[components setDay:12];

NSDate * dateFuturoSomeday = [calendar dateFromComponents:components];

NSCalendar * calendar1 = [NSCalendar currentCalendar];
NSDateComponents * components1 = [[NSDateComponents alloc] init];
[components1 setCalendar:calendar1];
[components1 setYear:2065];
[components1 setMonth:11];
[components1 setDay:13];

NSDate * dateFuturoCompleted = [calendar1 dateFromComponents:components1];




NSDateComponents * date1Components = [日历组件:comps
fromDate:today];
NSDateComponents * date2Components = [日历组件:comps
fromDate:date];
NSDateComponents * date3Components = [日历组件:comps
fromDate:dateFuturoSomeday];
NSDateComponents * date4Components = [calendar components:comps
fromDate:dateFuturoCompleted];


today = [calendar dateFromComponents:date1Components];
date = [calendar dateFromComponents:date2Components];
dateFuturoSomeday = [calendar dateFromComponents:date3Components];
dateFuturoCompleted = [calendar dateFromComponents:date4Components];



NSInteger daysAfterToday = [日历组件:NSDayCalendarUnit
fromDate:today toDate:date options:0] .day;
// NSString * section;
if(daysAfterToday< 0){
tmp = @0;
} else if(daysAfterToday == 0){
tmp = @1;
} else if(daysAfterToday> 0&&& 天后天< 2){
tmp = @2
}
else if([self.todoDueDate isEqualToDate:dateFuturoSomeday]){
tmp = @4;
}
else if([self.todoDueDate isEqualToDate:dateFuturoCompleted]){
tmp = @5;
}
else {
tmp = @3;
}






[self setPrimitiveValue:tmp forKey:@sectionIdentifier];

}


return tmp;

}


解决方案

检查在 cellForRowAtIndexPath 方法中,我能够从transient属性 sectionIdentifier 中检测值。这意味着我可以使用它来识别特殊的行项目,更新另一个属性的值,删除它。

  ToDoItem * todoitem = [self.fetchedResultsController objectAtIndexPath:indexPath]; 

NSString * sec = todoitem.sectionIdentifier;
NSString * quitar = todoitem.quitar;


if([sec isEqualToString:@1]&& [quitar isEqualToString:@si]&&&(numObjectsSec1> 1)){
NSLog(@DAS OBJEKT KANNGELÖSCHTWERDEN%@,todoitem.todoName);

NSManagedObjectContext * context = self.managedObjectContext;
[todoitem setValue:@si se puede borrarforKey:@borrar];
NSError * error = nil;
//将对象保存到持久存储
if(![context save:& error]){


[context deleteObject:todoitem];



};


I have a very weird question, but if I can explain it well, I guess the answer will not be so difficult. This is my current scenario:

I have a tableView with six fixed sections.

The sections are populated with core data objects.

I am using a transient attribute to decide on which section the object must be shown. This procedure is done in a NSManagedObject subclass. The transient attribute is called sectionIdentifier.

Due to the reason of using a transient attribute to decide on which section should appear every object, I decided to create a special row on each section, with the intention that there will be always at least one row on every section. This option will reduce the problem to have a nil section that would throw exceptions in case of adding or deleting rows, at least this has been a problem sometimes while testing the app.

That means that at the first launch every section has one row (I will call it the special row). And then the user can add/delete rows perfectly.

The problem I have now is that I need this special row to be remove if the section has new rows. At the same time, if the user deletes the last row in the section, the app automatically creates a new special row, so the section is never empty.

I know that this is not the best way to manage it, but due to my iOS knowledge, this is the best way I found to avoid exceptions while adding or removing rows from an empty section.

What I need is to delete the special row from a section when the user has added at least one new row to the section.

The object has a string attribute called quitar and for the special rows: quitar = @"si". This way, all special rows are easy to identify.

I am using this code to delete the special row if there are new rows in the section:

NSManagedObjectContext *context = self.managedObjectContext;

NSEntityDescription *entity=[NSEntityDescription entityForName:@"ToDoItem" inManagedObjectContext:context];
NSFetchRequest *fetch=[[NSFetchRequest alloc] init];
[fetch setEntity:entity];
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"quitar like 'si'"];
[fetch setPredicate:predicate];
NSError *fetchError;
NSArray *fetchedData=[self.managedObjectContext executeFetchRequest:fetch error:&fetchError];
for (NSManagedObject *item in fetchedData){

                [context deleteObject:item];
            } 

I was told that you cannot use transient attributes in a NSPredicate, and you can see in my code, that all special rows are deleted, not only the special from the desired section. I need your help to find a way to delete only the special row from the section I want, not from all the sections.

Thank you and sorry for my english.

EDITED

Please find below the way I assign sectionIdentifier in the NSManagedObject class ToDoItem:

-(NSString *)sectionIdentifier{

    [self willAccessValueForKey:@"sectionIdentifier"];
    NSString *tmp = [self primitiveValueForKey:@"sectionIdentifier"];
    [self didAccessValueForKey:@"sectionIdentifier"];




    if (!tmp){


        NSCalendar *calendar = [NSCalendar currentCalendar];
        NSInteger comps = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);

        NSDate *today = [NSDate date];
        NSDate *date = self.todoDueDate;

        NSDateComponents *components = [[NSDateComponents alloc] init];
        [components setCalendar:calendar];
        [components setYear:2065];
        [components setMonth:11];
        [components setDay:12];

        NSDate *dateFuturoSomeday = [calendar dateFromComponents:components];

        NSCalendar *calendar1 = [NSCalendar currentCalendar];
        NSDateComponents *components1 = [[NSDateComponents alloc] init];
        [components1 setCalendar:calendar1];
        [components1 setYear:2065];
        [components1 setMonth:11];
        [components1 setDay:13];

        NSDate *dateFuturoCompleted = [calendar1 dateFromComponents:components1];




        NSDateComponents *date1Components = [calendar components:comps
                                                        fromDate: today];
        NSDateComponents *date2Components = [calendar components:comps
                                                        fromDate: date];
        NSDateComponents *date3Components = [calendar components:comps
                                                        fromDate: dateFuturoSomeday];
        NSDateComponents *date4Components = [calendar components:comps
                                                        fromDate: dateFuturoCompleted];


        today = [calendar dateFromComponents:date1Components];
        date = [calendar dateFromComponents:date2Components];
        dateFuturoSomeday = [calendar dateFromComponents:date3Components];
        dateFuturoCompleted = [calendar dateFromComponents:date4Components];



        NSInteger daysAfterToday = [calendar components:NSDayCalendarUnit
                                               fromDate:today toDate:date options:0].day;
       // NSString *section;
        if (daysAfterToday < 0) {
            tmp  = @"0";
        } else if (daysAfterToday == 0) {
            tmp = @"1";
        } else if (daysAfterToday > 0 && daysAfterToday < 2) {
            tmp = @"2";
        }
        else if ([self.todoDueDate isEqualToDate:dateFuturoSomeday]){
            tmp = @"4";
        }
        else if ([self.todoDueDate isEqualToDate:dateFuturoCompleted]){
            tmp = @"5";
        }
        else {
            tmp = @"3";
        }






        [self setPrimitiveValue:tmp forKey:@"sectionIdentifier"];

    }


    return tmp;

}

解决方案

I have checked that at the cellForRowAtIndexPath method, I am able to detect the value from the transient attribute sectionIdentifier. That means that I can use it to identify the special row item, update the value of another attribute an delete it.

 ToDoItem *todoitem = [self.fetchedResultsController objectAtIndexPath:indexPath];

        NSString *sec = todoitem.sectionIdentifier;
        NSString *quitar = todoitem.quitar;


        if ([sec isEqualToString:@"1"] && [quitar isEqualToString:@"si" ] && ( numObjectsSec1 > 1 ) ){
            NSLog(@"DAS OBJEKT KANN GELÖSCHT WERDEN  %@", todoitem.todoName);

            NSManagedObjectContext *context = self.managedObjectContext;
            [todoitem setValue:@"si se puede borrar" forKey:@"borrar" ];
             NSError *error = nil;
             // Save the object to persistent store
             if (![context save:&error]) {


                 [context deleteObject: todoitem];



             };

这篇关于从特定部分删除核心数据对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆