我最近在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
答案 0 :(得分:1)
问题是,每次视图出现在self.lists
时,您都在执行新的获取请求并重新填充- (void)viewDidAppear:(BOOL)animated
。重新排序单元格时,您正在更改该本地数组中的顺序,但不会更改实际核心数据存储中的顺序,因此新获取的数据始终采用相同的顺序。
快速解决此问题的方法是将您的fetchrequest转移到只执行viewDidLoad
一次的地方。
当然,如果您需要在此视图之外(在应用程序重新启动,在其他地方)保持此顺序,您将需要实际保存整个数组或至少以某种方式保存对象。