moveRows与NSFetchedResultsController错误

use*_*007 1 core-data uitableview nsfetchedresultscontroller ios

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

我正在使用带有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]);
}
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

新错误

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

NSString *toSectionName = [[[toSection objects] lastObject] name];
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*rra 12

  1. 不要删除自己作为代表NSFetchedResultsController.这违背了该类的预期设计.如果那是"帮助"那么它掩盖了一个真正的问题.

  2. 不要用-performFetch;这种方法打电话.在NSFetchedResultsController将检测到的变化,并告诉你委托他们.

  3. 不要用-reloadData这种方法打电话.让委托方法进行NSFetchedResultsController重新排序.

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

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

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

我认为你的重新排序逻辑比它需要的更复杂.它也有助于查看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"];
    }
}
Run Code Online (Sandbox Code Playgroud)

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