gpt4 book ai didi

iphone - NSFetchedResultsController 的委托(delegate)方法处理

转载 作者:行者123 更新时间:2023-11-29 10:59:17 25 4
gpt4 key购买 nike

我有 UITableView 和 NSFetchedResultsController 附加到它。 FRC 的委托(delegate)方法完美运行,一切都很好,但我的单元格具有取决于单元格位置的自定义背景:1. 在 UITableView 的顶部(顶部有圆角的背景)2.在中间(没有圆角的背景)3.在底部(底部有圆角的背景)4. 单格(所有角都是圆的)。在我的单元格配置方法中,我计算了单元格的位置,并为其设置了适当的背景 View 。一切正常,但是FRC的delegate方法的实现出现了问题:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{

UITableView *tableView = self.agenciesTableView;

switch(type)
{
case NSFetchedResultsChangeInsert:
{
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
break;
}
case NSFetchedResultsChangeDelete:
{
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];
break;
}
case NSFetchedResultsChangeUpdate:
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

break;
}
case NSFetchedResultsChangeMove:
{

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
};
}

如您所见,这很常见,但有一个问题:如果单元格被插入到 UITableView 的顶部,它的配置方法 (cellForRowAtIndexPath) 被调用并且它正确绘制(带有圆顶角)但是它下面的单元格(以前在顶部)仍然带有圆顶角和我需要以某种方式重新绘制它。

-=已编辑=-

我更改了 FRC 的委托(delegate)方法以反射(reflect)更新逻辑:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{

UITableView *tableView = self.agenciesTableView;

switch(type)
{
case NSFetchedResultsChangeInsert:
{
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationNone];

//if we inserting a cell not to the middle of table view
//we need to update the previous cell (if we are inserting to the end)
// or the next cell (if we are inserting to the beggining)
if ([self controller:controller positionForCellAtIndexPath:newIndexPath]!=UITableViewCellPositionMiddle)
{
NSIndexPath *prevIndexPath=[NSIndexPath indexPathForRow:(newIndexPath.row+1) inSection:newIndexPath.section];
NSIndexPath *nextIndexPath=[NSIndexPath indexPathForRow:(newIndexPath.row-1) inSection:newIndexPath.section];
if ([self controller:controller cellExistsAtIndexPath:prevIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prevIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
if ([self controller:controller cellExistsAtIndexPath:nextIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:nextIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
};
break;
}
case NSFetchedResultsChangeDelete:
{
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];

//if we deleting a cell not fromo the middle of table view
//we need to update the previous cell (if we are deleting from the end)
//or the next cell (if we are deleting from the beggining)
if ([self controller:controller positionForCellAtIndexPath:indexPath]!=UITableViewCellPositionMiddle)
{
NSIndexPath *prevIndexPath=[NSIndexPath indexPathForRow:(indexPath.row+1) inSection:indexPath.section];
NSIndexPath *nextIndexPath=[NSIndexPath indexPathForRow:(indexPath.row-1) inSection:indexPath.section];
if ([self controller:controller cellExistsAtIndexPath:prevIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prevIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
if ([self controller:controller cellExistsAtIndexPath:nextIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:nextIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
};
break;
}
case NSFetchedResultsChangeUpdate:
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];

break;
}
case NSFetchedResultsChangeMove:
{

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];
if ([self controller:controller positionForCellAtIndexPath:indexPath]!=UITableViewCellPositionMiddle)
{
NSIndexPath *prevIndexPath=[NSIndexPath indexPathForRow:(indexPath.row+1) inSection:indexPath.section];
NSIndexPath *nextIndexPath=[NSIndexPath indexPathForRow:(indexPath.row-1) inSection:indexPath.section];
if ([self controller:controller cellExistsAtIndexPath:prevIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prevIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
if ([self controller:controller cellExistsAtIndexPath:nextIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:nextIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
};


[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
if ([self controller:controller positionForCellAtIndexPath:newIndexPath]!=UITableViewCellPositionMiddle)
{
NSIndexPath *prevIndexPath=[NSIndexPath indexPathForRow:(newIndexPath.row+1) inSection:newIndexPath.section];
NSIndexPath *nextIndexPath=[NSIndexPath indexPathForRow:(newIndexPath.row-1) inSection:newIndexPath.section];
if ([self controller:controller cellExistsAtIndexPath:prevIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prevIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
if ([self controller:controller cellExistsAtIndexPath:nextIndexPath])
{
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:nextIndexPath] withRowAnimation:UITableViewRowAnimationNone];
};
};
break;
}
};
}

但在这种情况下我得到一个错误:

2013-05-24 21:04:19.458 PharmaTouch[6994:fb03] *** Assertion failure in -[_UITableViewUpdateSupport _computeRowUpdates], /SourceCache/UIKit_Sim/UIKit-  1912.3/UITableViewSupport.m:386
2013-05-24 21:04:19.483 PharmaTouch[6994:fb03] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source. with userInfo (null)

-=EDITED2=-这是我的 controller:cellExistsAtIndexPath: 方法实现。它用于安全检查,以避免使用超出范围的 indexPath 参数调用 reloadRowsAtIndexPaths。

-(BOOL)controller:(NSFetchedResultsController *)controller cellExistsAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row<0)
{
return NO;
};

NSInteger numberOfRows = 0;
NSArray *sections = controller.sections;
if(sections.count > 0)
{
id <NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:indexPath.section];
numberOfRows = [sectionInfo numberOfObjects];
};
if (indexPath.row>(numberOfRows-1))
{
return NO;
}
else
{
return YES;
};
}

最佳答案

当您使用 UITableViewRowAnimationNone 时,您也可以只使用 reloadData 然后它会正确完成,因为所有行都将被刷新。

在你使用 UITableViewRowAnimationFade 的地方,考虑一下你对它的重视程度......

您需要在检查和重新加载方面更加全面。特别是,您需要从 FRC 获取正在更改的部分的部分信息。如果传入或传出行是第一行或最后一行,则需要刷新多行。沿着:

if first is changing and count > 1, also refresh second
if last is changing and count > 1, also refresh first

关于iphone - NSFetchedResultsController 的委托(delegate)方法处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16740610/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com