ios - 在 TableCells 中重新定位时出现问题

标签 ios objective-c uitableview core-data

我最近遇到了一个有趣的tutorial在 Ray Wenderlich 的网站上,了解如何通过使用长按手势并拖动 TableCell 来重新定位 TableCell,以更改顺序。一切正常,但我相信它会干扰我的核心数据获取,因为我重新定位单元格然后单击它,这会将我推到另一个 View ,当我返回时,单元格会恢复到我移动它们之前的顺序 - _- 我无法指出导致此问题的线路。因此,如果您有任何建议,请随时告诉我!谢谢!

表格 View .m:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // Fetch the lists from persistent data store
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"List"];
    self.lists = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:nil] mutableCopy];
    [self.tableView reloadData];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.lists.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...
    NSManagedObject *list = [self.lists objectAtIndex:indexPath.row];
    [cell.textLabel setText:[list valueForKey:@"name"]];

    return cell;
}

-(IBAction)add:(id)sender {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Add List" message:@"Create a New Wish List" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Save", nil];
    [alert setAlertViewStyle:UIAlertViewStylePlainTextInput];
    [alert setTag:2];
    [alert show];
    alert.delegate = self;
}

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != 0 && alertView.tag == 2) {
        UITextField *tf = [alertView textFieldAtIndex:0];
        NSManagedObjectContext *context = [self managedObjectContext];

        // Create a new managed object
        NSManagedObject *newList = [NSEntityDescription insertNewObjectForEntityForName:@"List" inManagedObjectContext:context];
        [newList setValue:tf.text forKey:@"name"];

        NSError *error = nil;
        // Save the object to persistent store
        if (![context save:&error]) {
            NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
        }
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"List"];
    self.lists = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:nil] mutableCopy];

    [self.tableView reloadData];

}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObjectContext *context = [self managedObjectContext];

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete object from database
        [context deleteObject:[self.lists objectAtIndex:indexPath.row]];

        NSError *error = nil;
        if (![context save:&error]) {
            NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]);
            return;
        }
        // Remove list from table view
        [self.lists removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

#pragma mark - Storyboard support

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    WishListView *wishListController = segue.destinationViewController;

    NSIndexPath *indexPath = [[self tableView] indexPathForSelectedRow];
    List *selectedList = self.lists[indexPath.row];
    wishListController.list = selectedList;
    wishListController.managedObjectContext = self.managedObjectContext;
}
-(void)viewDidLoad {
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                               initWithTarget:self action:@selector(longPressGestureRecognized:)];
    [self.tableView addGestureRecognizer:longPress];
}
- (IBAction)longPressGestureRecognized:(id)sender {

    UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
    UIGestureRecognizerState state = longPress.state;

    CGPoint location = [longPress locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];

    static UIView       *snapshot = nil;        ///< A snapshot of the row user is moving.
    static NSIndexPath  *sourceIndexPath = nil; ///< Initial index path, where gesture begins.

    switch (state) {
        case UIGestureRecognizerStateBegan: {
            if (indexPath) {
                sourceIndexPath = indexPath;

                UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

                // Take a snapshot of the selected row using helper method.
                snapshot = [self customSnapshotFromView:cell];

                // Add the snapshot as subview, centered at cell's center...
                __block CGPoint center = cell.center;
                snapshot.center = center;
                snapshot.alpha = 0.0;
                [self.tableView addSubview:snapshot];
                [UIView animateWithDuration:0.25 animations:^{

                    // Offset for gesture location.
                    center.y = location.y;
                    snapshot.center = center;
                    snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
                    snapshot.alpha = 0.98;

                    // Black out.
                    cell.backgroundColor = [UIColor clearColor];
                } completion:nil];
            }
            break;
        }
        case UIGestureRecognizerStateChanged: {
            CGPoint center = snapshot.center;
            center.y = location.y;
            snapshot.center = center;

            // Is destination valid and is it different from source?
            if (indexPath && ![indexPath isEqual:sourceIndexPath]) {

                // ... update data source.
               [self.lists exchangeObjectAtIndex:indexPath.row withObjectAtIndex:sourceIndexPath.row];

                // ... move the rows.
                [self.tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];

                // ... and update source so it is in sync with UI changes.
                sourceIndexPath = indexPath;
            }
            break;
        }
        default: {
            // Clean up.
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:sourceIndexPath];
            [UIView animateWithDuration:0.25 animations:^{

                snapshot.center = cell.center;
                snapshot.transform = CGAffineTransformIdentity;
                snapshot.alpha = 0.0;

                // Undo the black-out effect we did.
                cell.backgroundColor = [UIColor whiteColor];

            } completion:^(BOOL finished) {

                [snapshot removeFromSuperview];
                snapshot = nil;

            }];
            sourceIndexPath = nil;
            break;
        }
    }
}
- (UIView *)customSnapshotFromView:(UIView *)inputView {

    UIView *snapshot = [inputView snapshotViewAfterScreenUpdates:YES];
    snapshot.layer.masksToBounds = NO;
    snapshot.layer.cornerRadius = 0.0;
    snapshot.layer.shadowOffset = CGSizeMake(0.0, 0.0);
    snapshot.layer.shadowRadius = 5.0;
    snapshot.layer.shadowOpacity = 0.4;
    return snapshot;
}

@end

最佳答案

问题是每次 View 出现在 - (void)viewDidAppear:(BOOL)animated 中时,您都在执行新的获取请求并重新填充 self.lists。当您对单元格重新排序时,您是在更改该本地数组中的顺序,而不是在实际核心数据存储中的顺序,因此新获取的数据始终采用相同的顺序。

一个快速解决方法是将您的 fetchrequest 移动到只执行一次的地方,例如 viewDidLoad

当然,如果您需要此排序甚至在此 View 之外(在应用程序重新启动时,在其他地方)持续存在,您实际上需要保存整个数组或至少以某种方式保存对象排序。

关于ios - 在 TableCells 中重新定位时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22976514/

相关文章:

ios - iOS 7 中未调用 UIViewControllerTransitioningDelegate 方法

iphone - 实现在大型项目中到处使用的自己的功能的最简单方法是什么?

ios - appirator setSignificantEventsUntilPrompt iOS

iphone - UITableView 在彼此之上添加重复标签

iphone - 如何将 UItextfield 属性分配给另一个 UItextfield

ios - 如何从屏幕底部动画插入部分

iphone - UITableView 没有响应 performSelectorOnMainThread

ios - Swift:在仅下载一次的情况下多次使用托管 JSON 文件内容的最佳方式

iOS UITableViewCell 取消选择问题

用于 native iOS iPod 控制的 Javascript