Ios6 是否重新加载UICollectionView页眉或页脚?
我在另一个更新UICollectionView头的线程中获取了一些数据。但是,我还没有找到一种有效的方法来重新加载补充视图,如页眉或页脚Ios6 是否重新加载UICollectionView页眉或页脚?,ios6,uicollectionview,Ios6,Uicollectionview,我在另一个更新UICollectionView头的线程中获取了一些数据。但是,我还没有找到一种有效的方法来重新加载补充视图,如页眉或页脚 我可以调用collectionView reloadSections:,但这会重新加载整个部分,这是不必要的collectionView-reloadeitemsatindexpaths:似乎只针对单元格(不是补充视图)。在报头本身上调用setNeedsDisplay,似乎也不起作用。我遗漏了什么吗?这里有两种方法可以做到这一点 一,。 创建可变模型以支持最终
我可以调用
collectionView reloadSections:
,但这会重新加载整个部分,这是不必要的collectionView-reloadeitemsatindexpaths:
似乎只针对单元格(不是补充视图)。在报头本身上调用setNeedsDisplay
,似乎也不起作用。我遗漏了什么吗?这里有两种方法可以做到这一点
一,。
创建可变模型以支持最终可用的数据。在UICollectionReusableView的继承类中使用KVO来观察更改,并在可用时使用新数据更新标题视图
[model addObserver:headerView
forKeyPath:@"path_To_Header_Data_I_care_about"
options:(NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
context:NULL];
然后在header视图中实现listener方法
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
二,。
将通知侦听器添加到视图,并在数据成功可用时发布通知。缺点是,这是一个应用程序范围,不是一个干净的设计
// place in shared header file
#define HEADER_DATA_AVAILABLE @"Header Data Available Notification Name"
// object can contain userData property which could hole data needed.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(headerDataAvailable:) name:HEADER_DATA_AVAILABLE object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:HEADER_DATA_AVAILABLE object:nil];
我遇到了同样的问题,最后我使用视图的标记来编辑标签:
UICollectionReusableView *footer = (UICollectionReusableView*)[self.collectionView viewWithTag:999];
UILabel *footerLabel = (UILabel*)[footer viewWithTag:100];
正如您所说,不需要重新加载整个部分,这也会取消单元格上的任何动画。我的解决方案并不理想,但很简单。我也遇到了同样的问题。我尝试了@BobWorks的答案,它工作得很好,如果该单元被重新使用,否则它不会。因此,我试图找到一种更干净的方法来实现这一点,在performBatchUpdate(completion block)之后重新加载整个UICollectionView,效果非常好。它重新加载集合,而不取消InsertItemSatineXPath中的动画。事实上,我个人对最近的两个答案投了赞成票,因为我觉得这很有效,但就我而言,这是最干净的方式
[self.collectionView performBatchUpdates:^{
// perform indexpaths insertion
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
你也可以使用(懒惰的方式)
更复杂的是提供一个上下文
collectionView.collectionViewLayout.invalidateLayout(with: context) // swift
[[_collectionView collectionViewLayout] invalidateLayoutWithContext:context] // objc
然后,您可以自行创建或配置上下文,以告知应更新的内容。请参见:
其中有一个功能,您可以覆盖:
invalidateSupplementaryElements(ofKind:at:) // swift
另一个选项是(如果您已经加载了正确的页眉/页脚/补充视图),并且您只想使用新数据更新视图,然后可以使用以下函数之一检索它:
supplementaryView(forElementKind:at:)//获取特定的视图
visiblesupplementaryview(of kind:)//所有可见视图
具有可见单元格的可见单元格也一样。只获取视图而不完全重新加载视图的优点是,单元格保留了视图的状态。当表格视图单元格使用滑动删除/编辑/etc时,这尤其好,因为在重新加载单元格后,该状态将丢失
如果您感到狂热,当然也可以编写一些扩展,使用泛型仅检索给定类型的单元格/补充视图
if let view = supplementaryView(forType: MySupplementaryView.self, at: indexPath) {
configure(view, at indexPath)
}
这假设您有一个函数,该函数在示例中使用视图的类名注册/出列视图。我发表了一篇关于此的帖子,下面是我为只更新当前加载到内存中的节标题所做的操作:
- 添加一个weakToStrong
NSMapTable
。创建标头时,使用indexPath对象将标头添加为弱持有键。如果我们重用头,我们将更新indexPath
- 当您需要更新标题时,现在可以根据需要从
NSMapTable
枚举对象/键
这个问题很老,但一个简单的方法是设置一个延迟,该延迟涵盖了视图在更新视图时设置动画和禁用动画的时间…通常删除或插入大约需要35秒,所以只需执行以下操作:
delay(0.35){
UIView.performWithoutAnimation{
self.collectionView.reloadSections(NSIndexSet(index: 1))
}
Swift 3/4/5版本:
collectionView.collectionViewLayout.invalidateLayout()
小心强>
如果同时更改collectionView
项目的数量(例如,仅当加载了所有单元格时才显示页脚),它将崩溃。您需要首先重新加载数据,以确保在invalidateLayout()之前和之后的项目数相同。
:
当布局无效时,补充视图的框架尺寸发生变化时,我的问题就出现了。补充意见似乎并不新鲜。原来是这样,但我是以编程方式构建UICollectionReusableView
对象,而不是删除旧的UILabel
子视图。因此,当集合视图将每个标题视图出列时,UILabel会堆积起来,导致外观不稳定
解决方案是将每个UICollectionReusableView完全构建在SupplmentalElementOfKind:(NSString*)kind atIndexPath:(NSIndexPath*)indexPath
方法的视图中,首先是a)从出列单元中移除所有子视图,然后b)从项目的布局属性获取框架大小,以允许添加新的子视图
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
yourClass *header = (yourClass *)[collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"identifier" forIndexPath:indexPath];
[[header viewWithTag:1] removeFromSuperview]; // remove additional subviews as required
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForSupplementaryElementOfKind:kind atIndexPath:indexPath];
CGRect frame = attributes.frame;
UILabel *label = [[UILabel alloc] initWithFrame: // CGRectMake based on header frame
label.tag = 1;
[header addSubview:label];
// configure label
return header;
}
我已使用上述方法获取当前标题,并成功更新了标题上的子视图。我得到了一个完美的解决方案:
let footerView = self.collectionView.visibleSupplementaryViews(ofKind: UICollectionView.elementKindSectionFooter)
现在,您可以使用以下命令访问footerView的所有子视图:
footerView[0].subviews[0]
如果页脚视图中有标签,则:
let label: UILabel = footerView[0].subviews[0] as? UILabel ?? UILabel()
最后一步:
label.text = "Successfully Updated Footer."
如果让footerView=collectionView.subviews.first(其中:{$0正在加载FooterCell})作为?加载页脚单元格{
footerView.isLoading=.loading
}我没有使用KVO,但我监听了数据更新,在自定义头类上设置了字段,并在其上调用了setNeedsDisplay,但没有任何更改。与设计如何更新标题相比,我在让标题自我刷新方面遇到的问题更多。您是否尝试调用invalidateLayout。这会刷新你的标题吗?在最简单的层次上,当数据返回时,你想显示什么?我只是有一些UILabel需要更新。我不得不重写它以使用单元格而不是标题——他说
let headerView = collectionView.visibleSupplementaryViews(ofKind: UICollectionView.elementKindSectionHeader)[0] as! UICollectionReusableView
let footerView = self.collectionView.visibleSupplementaryViews(ofKind: UICollectionView.elementKindSectionFooter)
footerView[0].subviews[0]
let label: UILabel = footerView[0].subviews[0] as? UILabel ?? UILabel()
label.text = "Successfully Updated Footer."