我已经UICollectionViewLayout为我实现了一个自定义UICollectionView,也是一个UICollectionViewLayoutInvalidationContext希望获得良好性能的自定义。
在我的第一个用例中,我有浮动标题,在滚动期间我只使需要滑动的标题无效。
我这样做如下:
YES从shouldInvalidateLayoutForBoundsChange:.invalidationContextForBoundsChange:方法被调用时,我通过调用invalidateSupplementaryElementsOfKind:atIndexPaths:.invalidateLayoutWithContext:被调用时,我真的不需要做任何事情,因为使标头无效足以使以下关键事情发生:layoutAttributesForSupplementaryViewOfKind:atIndexPath:被调用而不是从prepareLayout.这很好用。
我的第一个问题是:这个场景如何抑制prepareLayout序列?起初我认为向上下文添加任何数据(在这种情况下是陈旧补充的索引路径)足以让 Apple 假设我知道我在做什么(iOS8-wise)而不是调用prepareLayout. 我知道不再相信这一点,正如您将在下面看到的那样。
我的第二个用例:在实践中,我的数据源几乎总是只在最后添加项目。对于我的布局算法,这意味着较早(indexPath-wise)项目的布局不会因新数据而失效。我不想花时间重新计算我不需要的潜在大量布局属性。因此,当客户端代码调用时,我需要做“正确的事情”:
[collection insertItemsAtIndexPaths: newIndices];
Run Code Online (Sandbox Code Playgroud)
通过注意最早的 indexPath 是什么newIndices并从那里开始重新计算我的布局。几乎总是newIndices从最后开始,并且没有现有的单元格变得陈旧——因此 Apple 应该只询问我的布局对象的新单元格的属性。
但请注意,invalidationContextForBoundsChange:对于插入/删除/移动调用没有类似的方法。所以我无法预先配置我的上下文,并说明什么索引来来去去。
所以在调用内部insertItemsAtIndexPaths:会发生什么:
invalidateLayout被调用之前。在初始化时,self.invalidateEverything并且self.invalidateDataSourceCounts是 (NO,NO) (并且它们是只读的)。invalidateLayoutWithContext:现在被调用,invalidateDataSourceCounts设置为YES--Apple 只告诉我我的计数已经过时。这是没用的,因为它没有告诉我关于在哪里重新开始布局计算的任何信息。但这是我第一次(也是唯一一次)注意到某事或做某事。prepareLayout被叫到——Grrr!我不想重新开始。我不想 …下面是一个典型的 C 函数,它采用经典函数指针作为参数:
int DoThingy( const char* stuff, int(*helper)(int))
{
int result = 0;
//...call helper...
return result;
}
Run Code Online (Sandbox Code Playgroud)
下面我用一个非捕获 lambda 来调用上面的内容,它神奇地“降级”为函数指针。在“A”处,转换是隐式的。在“B”处,它是明确的。都好。
void UseThingy()
{
auto lam = [](int)->int {
return 42;
};
int i;
i = DoThingy( "hello", lam); //"A" works
int (*ptr)(int) = lam;
i = DoThingy( "hello", ptr); //"B" works
}
Run Code Online (Sandbox Code Playgroud)
但在这个新示例中,回调函数的签名取决于模板类型:
template <typename T>
int DoThingy2( const char* stuff, int (*helper)(T))
{
int result = 0;
//...call helper...
return result;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用上面的这个版本时,“C”行甚至无法编译。然而“D”处的显式版本是有效的。什么?为什么这些不一样?请注意,当我在“E”处给出显式模板参数时,它可以工作,但当然可以<int>从 的签名推断出来lam …