2014-04-10 25 views
0

我最近在Ray Wenderlich的網站上發現了一個有趣的tutorial,其中介紹瞭如何使用長按手勢並拖動它們來更改順序來重新定位TableCells。這一切都正常,但我相信它干擾了我的核心數據獲取,因爲我重新定位了單元格,然後單擊它將其推到另一個視圖,當我返回時,單元格會返回到它們在移動它們之前的順序 - _-我不能指出造成這個問題的路線。所以,如果您有任何建議,請隨時讓我知道!謝謝!重新定位表格細胞時的問題

TableView.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 

回答

1

的問題是,你正在執行一個新的讀取請求,每個視圖顯示在- (void)viewDidAppear:(BOOL)animated時間再植self.lists。重新排序單元格時,您將更改該本地數組中的順序,但不會更改實際的核心數據存儲區中的順序,因此新獲取的數據總是以相同的順序排列。

一個快速解決這個問題的方法是將fetchrequest移動到只能執行一次的地方,如viewDidLoad

當然,如果你需要這個順序來保持這個視圖之外(在應用程序重新啓動,在其他地方),你需要實際保存整個數組或至少對象以某種方式排序。