Ios 奇怪的重新排序单元格动画/小故障
我有一个奇怪的动画错误,我认为是基于我的“Ios 奇怪的重新排序单元格动画/小故障,ios,core-data,uitableview,nsfetchedresultscontroller,Ios,Core Data,Uitableview,Nsfetchedresultscontroller,我有一个奇怪的动画错误,我认为是基于我的“moveUp”和“moveDown”方法。我的编辑代码基于,所以这就是这些方法的起源 编辑是成功的,但是,在玩了一小会儿之后,它开始表现得非常奇怪。单元格被复制,某些单元格在按下“完成”按钮后仍保持编辑模式,即使其他单元格发生更改,但奇怪的是,如果您尝试移动仍处于编辑状态的单元格,它们只会悬停在不可编辑的单元格上。这一切都很令人困惑。我不知道这是我的MoveRowatineXpath方法中的问题,还是我在自定义方法中设置的实际移动中的问题。我在下面列出了
moveUp
”和“moveDown
”方法。我的编辑代码基于,所以这就是这些方法的起源
编辑是成功的,但是,在玩了一小会儿之后,它开始表现得非常奇怪。单元格被复制,某些单元格在按下“完成”按钮后仍保持编辑模式,即使其他单元格发生更改,但奇怪的是,如果您尝试移动仍处于编辑状态的单元格,它们只会悬停在不可编辑的单元格上。这一切都很令人困惑。我不知道这是我的MoveRowatineXpath方法中的问题,还是我在自定义方法中设置的实际移动中的问题。我在下面列出了它的行为示例。(对不起,应用程序的背景是白色的,所以看起来代码被按下了。)
UITableViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]) {
NSLog(@"Error! %@", error);
abort();
}
}
- (IBAction)unwindToMainViewController:(UIStoryboardSegue *)unwindSegue {
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (NSUInteger)countEvents
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSFetchRequest *request = [[NSFetchRequest alloc] init] ;
[request setEntity: entity];
NSError *error = nil;
NSUInteger count = [context countForFetchRequest:request error:&error];
if (count == NSNotFound) {
count = 0;
}
return count;
}
- (void)insertNewObject:(id)sender
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Top" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSUInteger orderIdx = 1 + [self countEvents];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"Top" inManagedObjectContext:context];
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
[newManagedObject setValue:[NSNumber numberWithInteger:orderIdx] forKey:@"orderIdx"];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
-(NSManagedObjectContext*)managedObjectContext {
return [(TTAppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(UITableViewCell*)sender {
if ([[segue identifier]isEqualToString:@"addTop"]) {
UINavigationController *navigationController = segue.destinationViewController;
AddTopViewController *addTopViewController = (AddTopViewController*) navigationController.topViewController;
Top *addTop = [NSEntityDescription insertNewObjectForEntityForName:@"Top" inManagedObjectContext:self.managedObjectContext];
addTopViewController.addTop = addTop;
}
if ([[segue identifier]isEqualToString:@"showList"]) {
TopDetailTableViewController *topDetailTableViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Top *selectedTop = (Top *)[self.fetchedResultsController objectAtIndexPath:indexPath];
topDetailTableViewController.selectedTop = selectedTop;
UITableViewCell *selectedCell = (UITableViewCell *)sender;
topDetailTableViewController.title = selectedCell.textLabel.text;
}
}
-(void) viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
// Configure the cell...
Top *top = [self.fetchedResultsController objectAtIndexPath:indexPath];
if (!cell) {
cell = [[UITableViewCell alloc] init];
cell.showsReorderControl = YES;
}
cell.textLabel.text = top.topName;
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)adjustOrderIdxForRow:(NSInteger)row inSection:(NSInteger)section by:(NSInteger)adjustment
{
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
Top *top = [[self fetchedResultsController] objectAtIndexPath:path];
top.orderIdx = [NSNumber numberWithInteger:[top.orderIdx integerValue] + adjustment];
}
- (void)moveUp:(NSIndexPath*)fromIndexPath to:(NSIndexPath*)toIndexPath
{
NSInteger section = fromIndexPath.section;
Top *objectMoved = [[self fetchedResultsController] objectAtIndexPath:fromIndexPath];
Top *firstObject = [[self fetchedResultsController] objectAtIndexPath:toIndexPath];
NSNumber *firstOrderIdx = firstObject.orderIdx;
for (NSInteger i = toIndexPath.row; i <= fromIndexPath.row - 1; i++) {
[self adjustOrderIdxForRow:i inSection:section by:-1];
}
objectMoved.orderIdx = firstOrderIdx;
}
- (void)moveDown:(NSIndexPath*)fromIndexPath to:(NSIndexPath*)toIndexPath
{
NSInteger section = fromIndexPath.section;
Top *objectMoved = [[self fetchedResultsController] objectAtIndexPath:fromIndexPath];
Top *lastObject = [[self fetchedResultsController] objectAtIndexPath:toIndexPath];
NSNumber *lastOrderIdx = lastObject.orderIdx;
for (NSInteger i = fromIndexPath.row + 1; i <= toIndexPath.row; i++) {
[self adjustOrderIdxForRow:i inSection:section by:1];
}
objectMoved.orderIdx = lastOrderIdx;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
BOOL moveDown = toIndexPath.row > fromIndexPath.row;
moveDown ? [self moveDown:fromIndexPath to:toIndexPath] : [self moveUp:fromIndexPath to:toIndexPath];
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error when swapping objects order: %@, %@", error, [error userInfo]);
abort();
}
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Top *event = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(@"Path: %@, orderIdx: %@", indexPath, event.orderIdx);
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Top" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"orderIdx" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
-(void)viewDidLoad
{
[超级视图下载];
self.navigationItem.leftBarButtonItem=self.editButtonItem;
n错误*错误=nil;
如果(![[self-fetchedResultsController]性能检测:&错误]){
NSLog(@“Error!%@”,Error);
中止();
}
}
-(iAction)解除对InviewController的绑定:(UIStoryboardSegue*)解除绑定{
}
-(id)initWithStyle:(UITableViewStyle)样式
{
self=[super initWithStyle:style];
如果(自我){
//自定义初始化
}
回归自我;
}
-(整数)countEvents
{
NSManagedObjectContext*上下文=[self.fetchedResultsController managedObjectContext];
NSEntityDescription*实体=[[self.fetchedResultsController fetchRequest]实体];
NSFetchRequest*request=[[NSFetchRequest alloc]init];
[请求集合实体:实体];
n错误*错误=nil;
NSU整数计数=[FetchRequest的上下文计数:请求错误:&错误];
if(count==NSNotFound){
计数=0;
}
返回计数;
}
-(void)insertNewObject:(id)发送方
{
NSFetchRequest*fetchRequest=[[NSFetchRequest alloc]init];
NSManagedObjectContext*上下文=[self.fetchedResultsController managedObjectContext];
NSEntityDescription*entity=[NSEntityDescription entityForName:@“Top”inManagedObjectContext:context];
[FetchRequestSetEntity:entity];
NSUInteger orderIdx=1+[self countEvents];
NSManagedObject*newManagedObject=[NSEntityDescription insertNewObjectForEntityForName:@“Top”inManagedObjectContext:context];
//如果合适,请配置新的托管对象。
//通常您应该使用访问器方法,但是在这里使用KVC可以避免向模板添加自定义类。
[newManagedObject setValue:[NSNumber numberWithInteger:orderIdx]forKey:@“orderIdx”];
//保存上下文。
n错误*错误=nil;
如果(![上下文保存:&错误]){
//将此实现替换为适当处理错误的代码。
//abort()导致应用程序生成崩溃日志并终止。您不应该在装运应用程序中使用此函数,尽管它在开发过程中可能很有用。
NSLog(@“未解决的错误%@,%@”,错误,[error userInfo]);
中止();
}
}
-(NSManagedObjectContext*)managedObjectContext{
返回[(TTAppDelegate*)[[UIApplication sharedApplication]委托]managedObjectContext];
}
-(void)prepareForSegue:(UIStoryboardSegue*)segue发送方:(UITableViewCell*)发送方{
if([[segue identifier]IsequalString:@“addTop”]){
UINavigationController*navigationController=segue.destinationViewController;
AddTopViewController*AddTopViewController=(AddTopViewController*)navigationController.topViewController;
Top*addTop=[NSEntityDescription insertNewObjectForEntityForName:@“Top”在managedObjectContext:self.managedObjectContext中];
addTopViewController.addTop=addTop;
}
if([[segue identifier]IsequalString:@“showList”]){
TopDetailTableViewController*TopDetailTableViewController=[segue destinationViewController];
NSIndexPath*indexPath=[self.tableView indexPathForSelectedRow];
Top*selectedTop=(Top*)[self.fetchedResultsController对象索引路径:indexPath];
topDetailTableViewController.selectedTop=selectedTop;
UITableViewCell*selectedCell=(UITableViewCell*)发送方;
topDetailTableViewController.title=selectedCell.textLabel.text;
}
}
-(无效)视图将显示:(BOOL)动画{
[self.tableView重载数据];
}
-(无效)未收到记忆警告
{
[超级记忆警告];
//处置所有可以重新创建的资源。
}
#pragma标记-表视图数据源
-(NSInteger)表格视图中的节数:(UITableView*)表格视图
{
//返回节数。
返回[[self.fetchedResultsController节]计数];
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节
{
//返回节中的行数。
id sectionInfo=[self.fetchedResultsController sections][section];
返回[sectionInfo numberOfObjects];
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell*cell=[tableView dequeueReusableCellWithIdentifier:@“cell”forIndexPath:indexPath];
//配置单元格。。。
Top*Top=[self.fetchedResultsController对象索引路径:indexPath];
如果(!单元格){
cell=[[UITableViewCell alloc]init];
cell.showsReorderControl=是;
}
cell.textlab.text=top.topName;
[self-configureCell:cell-atIndexPath:indexPath];
返回单元;
}
-(void)tableView:(UITableView*)tableView提交的编辑样式:(UITableViewCellEditingStyle)行的编辑样式索引路径:(NSIndexPath*)索引路径
{
如果(editingStyle==UITableViewCellEditingStyleDelete){
NSManagedObjectContext*上下文=[self.fetchedResultsController managedObjectContext];
[上下文删除对象:[self.fetchedResultsController对象索引路径:indexPath]];
NSErr
cell.clipsToBounds = YES;
[self.tableView bringSubViewToFront:cell];
[self.tableView beginUpdated];
// Drag and Drop Cell
// Update data set as needed
[self.tableView endUpdates];
[self.tableView reloadData];
-(void)controllerDidChangeContent
- (void)adjustOrderIdxForRow:(NSInteger)row inSection:(NSInteger)section by:(NSInteger)adjustment
{
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
Top *top = [[self fetchedResultsController] objectAtIndexPath:path];
top.orderIdx = [NSNumber numberWithInteger:[top.orderIdx integerValue] + adjustment];
[self.tableView reloadData];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
[self.tableView reloadData];
}