Ios6 是否重新加载UICollectionView页眉或页脚?

Ios6 是否重新加载UICollectionView页眉或页脚?,ios6,uicollectionview,Ios6,Uicollectionview,我在另一个更新UICollectionView头的线程中获取了一些数据。但是,我还没有找到一种有效的方法来重新加载补充视图,如页眉或页脚 我可以调用collectionView reloadSections:,但这会重新加载整个部分,这是不必要的collectionView-reloadeitemsatindexpaths:似乎只针对单元格(不是补充视图)。在报头本身上调用setNeedsDisplay,似乎也不起作用。我遗漏了什么吗?这里有两种方法可以做到这一点 一,。 创建可变模型以支持最终

我在另一个更新UICollectionView头的线程中获取了一些数据。但是,我还没有找到一种有效的方法来重新加载补充视图,如页眉或页脚


我可以调用
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."