moveRows与NSFetchedResultsController错误

时间:2014-01-08 16:12:44

标签: ios uitableview core-data nsfetchedresultscontroller

我在这里有一个错误,我找不到它所以我希望你敏锐的眼睛会这样!

我正在使用带有tableView的FRC。 FRC是按keyPath排序的部分,然后按“displayOrder”排序 - 通常。

每个部分的详细信息“displayOrder”从1开始,所以当我插入一个项目时,在另一个方法中,它会转到该部分的索引0。

我想遍历受影响的部分,并从1开始重新分配“displayOrder”。

在重新订购期间,代码适用于: 在重新排序的单元格向上移动而不是向下移动的任何部分内重新排序。

代码不适用于...单击一个单元格但不移动它...代码因某种原因改变了顺序,从而改变了单元格的顺序。 - 当我点击一个单元格时,它与它上面的其他单元格重新排序。

我以前有这个工作,我不知道发生了什么。

感谢您的帮助。

-Edited -

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath

NSError *error = nil;

NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];

TheDetail *fromThing = [self.fetchedResultsController objectAtIndexPath:fromIndexPath];
TheDetail *toThing = [self.fetchedResultsController objectAtIndexPath:toIndexPath];

NSPredicate *catetgoryPredicate = [NSPredicate predicateWithFormat:@"relationshipToTheCategory.name == %@", fromThing.relationshipToTheCategory.name];

NSMutableArray *allThings = [[[self.fetchedResultsController fetchedObjects] filteredArrayUsingPredicate:catetgoryPredicate] mutableCopy];

NSPredicate *fromPredicate = [NSPredicate predicateWithFormat:@"relationshipToTheSection.name == %@", fromThing.relationshipToTheSection.name];
NSPredicate *toPredicate = [NSPredicate predicateWithFormat:@"relationshipToTheSection.name == %@", toThing.relationshipToTheSection.name];

[allThings removeObject:fromThing];
[allThings insertObject:fromThing atIndex:toIndexPath.row];

//if the sections are NOT the same, reorder by section otherwise reorder the one section
if (![fromThing.relationshipToTheSection.name isEqual:toThing.relationshipToTheSection.name]) {

    //Change the from index section's relationship and save, then grab all objects in sections and re-order
    [fromThing setRelationshipToTheSection:toThing.relationshipToTheSection];

    if ([context save:&error]) {
        NSLog(@"The setting section save was successful!");
    } else {
        NSLog(@"The setting section save was not successful: %@", [error localizedDescription]);
    }

    NSMutableArray *fromThings = [[allThings  filteredArrayUsingPredicate:fromPredicate]mutableCopy];
    NSInteger i = 1;
    for (TheDetail *fromD in fromThings) {
        [fromD setValue:[NSNumber numberWithInteger:i] forKey:@"displayOrder"];
        i++;

    }
    //reset displayOrder Count, the re-order the other section
    i = 1;
    NSMutableArray *toThings = [[allThings filteredArrayUsingPredicate:toPredicate]mutableCopy];
    for (TheDetail *toD in toThings) {
        [toD setValue:[NSNumber numberWithInteger:i] forKey:@"displayOrder"];
        i++;

    }
} else {
    NSMutableArray *fromThings = [[allThings filteredArrayUsingPredicate:fromPredicate]mutableCopy];
    NSInteger i = 1;
    for (TheDetail *fromD in fromThings) {
        [fromD setValue:[NSNumber numberWithInteger:i] forKey:@"displayOrder"];
        i++;
    }
}
if ([context save:&error]) {
    NSLog(@"The save was successful!");
} else {
    NSLog(@"The save was not successful: %@", [error localizedDescription]);
}

FRC

if (_fetchedResultsController != nil)
{
    return _fetchedResultsController;
}
NSManagedObjectContext *context = [[self appDelegate]managedObjectContext];

//Construct the fetchResquest
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSEntityDescription *detail = [NSEntityDescription entityForName:@"TheDetail"    inManagedObjectContext:context];
[fetchRequest setEntity:detail];

//Add predicate 
NSString *category = @"1";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"relationshipToTheCategory == %@", category];
[fetchRequest setPredicate:predicate];

//Add sort descriptor
NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"relationshipToTheSection.displayOrder" ascending:YES];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"displayOrder" ascending:YES];

NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor2, sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];


//Set fetchedResultsController
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"relationshipToTheSection.name" cacheName:@"Root"];
NSError *error = nil;


self.fetchedResultsController = theFetchedResultsController;
self.fetchedResultsController.delegate = self;
[self.fetchedResultsController performFetch:&error];

return _fetchedResultsController;

新错误

    Section *toSection = [[self fetchedResultsController] sections][[toIndexPath section]];

NSString *toSectionName = [[[toSection objects] lastObject] name];

在这里我得到IB中的错误“没有可见的@interface for”DSection“声明了选择器'对象'。

1 个答案:

答案 0 :(得分:12)

  1. 请勿将自己移除为NSFetchedResultsController的代理人。这违背了该类的预期设计。如果那是“帮助”那么它掩盖了一个真正的问题。

  2. 请勿使用此方法调用-performFetch;NSFetchedResultsController会检测到更改并告知您的代表。

  3. 请勿使用此方法调用-reloadData。让NSFetchedResultsController的委托方法进行重新排序。

  4. 始终,始终,始终捕获核心数据保存上的错误。即使你真的不需要在这里保存(这是用保存阻止UI的不好的时候),你应该总是捕获错误,然后观察结果,否则隐藏错误。

  5. 目前尚不清楚-save:正在做什么。你没有改变任何东西。

  6. 所以这是你正在做的很多工作,你不需要这样做。你正在与框架作斗争并使事情更加艰难。

    你的重新排序逻辑比它需要的更复杂,我认为。查看NSFetchedResultsController初始化也会有所帮助。但我猜您有基于name的部分,然后按displayOrder排序。如果是这种情况,这个代码可以更清洁,这将使问题更加明显。

    我的问题是,你是否用断点检查?当一行未实际移动时,此代码是否会触发?您是否应该检查toIndexPathfromIndexPath是否相同?

    更新

    您无需在此处保存上下文。这是一种UI方法,保存会导致延迟,这会使UI响应缓慢。 稍后保存。

    您无需在此处运行NSFetchRequest。这也会击中磁盘并导致UI延迟。您需要的每条信息都已经在NSFetchedResultsController内的内存中。使用现有的对象关系来检索您做出决策所需的数据。

    调用实体The*违反了Objective-C命名约定。 “the”,“is”,“are”等词语不属于实体或类名。

    考虑这段代码:

    - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
    {
        NSManagedObjectContext *context = [[self fetchedResultsController] managedObjectContext];
    
        TheDetail *fromThing = [[self fetchedResultsController] objectAtIndexPath:fromIndexPath];
        Section *toSection = [[self fetchedResultsController] sections][[toIndexPath section]];
    
        NSString *toSectionName = [[[toSection objects] lastObject] name];
        NSString *fromSectionName = [[fromThing relationshipToTheSection] name];
        if ([toSectionName isEqualToString:fromSectionName]) {
            //Same section, easy reorder
    
            //Move the object
            NSMutableArray *sectionObjects = [[[[self fetchedResultsController] sections][[fromIndexPath section]] objects] mutableCopy];
            [sectionObjects removeObject:fromThing];
            [sectionObjects insertObject:fromThing atIndex:[toIndexPath row]];
    
            //Reorder
            NSInteger index = 1;
            for (TheDetail *thing in sectionObjects) {
                [thing setValue:@(index) forKey:@"displayOrder"];
            }
    
            return; //Early return to keep code on the left margin
        }
    
        NSMutableArray *sectionObjects = [[[[self fetchedResultsController] sections][[fromIndexPath section]] objects] mutableCopy];
        [sectionObjects removeObject:fromThing];
    
        //Reorder
        NSInteger index = 1;
        for (TheDetail *thing in sectionObjects) {
            [thing setValue:@(index) forKey:@"displayOrder"];
        }
    
        if ([[toSection numberOfObjects] count] == 0) {
            [fromThing setValue:@(0) forKey:@"displayOrder"];
            //How do you determine the name?
            return;
        }
    
        sectionObjects = [[toSection objects] mutableCopy];
        [sectionObjects insertObject:fromThing atIndex:[toIndexPath row]];
    
        //Reorder
        NSInteger index = 1;
        for (TheDetail *thing in sectionObjects) {
            [thing setValue:@(index) forKey:@"displayOrder"];
        }
    }
    

    没有抓取也没有保存。我们只使用内存中的内容,因此非常快。除了我留下的一条评论之外,这应该是C& P-able。