ios - 自定义 UICollectionViewLayout 和 float 补充标题 View 崩溃

标签 ios swift uicollectionview uicollectionviewlayout

我正在尝试创建一个代表网格的 UICollectionView,我想在沿着 y 轴 float 的顶部边缘创建一个标尺( float 标题 View )。 所以,就像在 UITableView 中一样,这个 View 基本上应该只随着屏幕顶部的内容滚动。我希望描述足够清楚。理论就这么多,让我们进入实践部分吧!

这是我现在正在使用的:

  • 我注册了 GridRulerView 类,它是 UICollectionReusableView 与 Collection View 。
  • 我返回正确类型的补充 View 的正确大小和没有标题的 CGSizeZero。
  • 我实现了 viewForSupplementaryElementOfKind::

    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
    {
        var reusableHeaderView : UICollectionReusableView!
        if kind == GridRulerView.Kind{
            reusableHeaderView = collectionView.dequeueReusableSupplementaryViewOfKind(GridRulerView.Kind, withReuseIdentifier: GridRulerView.Kind, forIndexPath: indexPath) as! UICollectionReusableView
    
        }
        return reusableHeaderView
    }
    

我有一个自定义 UICollectionViewLayout 具有以下内容 layoutAttributesForElementsInRect: 方法:

override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {

        var attribs = [UICollectionViewLayoutAttributes]()
        for (indexPath, attrs) in self.attributes{
            if CGRectIntersectsRect(rect, attrs.frame) {
                attribs.append(attrs)
            }
        }

        var headerAttributes = GridViewRulerAttributes(forSupplementaryViewOfKind: GridRulerView.Kind, withIndexPath: NSIndexPath(forItem: 0, inSection: 0))
        headerAttributes.zIndex = 500
        headerAttributes.frame = CGRectMake(0, self.collectionView!.contentOffset.y, self.preCalculatedContentSize.width, 80)
        attribs.append(headerAttributes)

        return attribs

}

当我启动该应用程序时,一切看起来都很棒,完全符合我的要求。 但是,一旦我将 collectionView 滚动到它的边界之外(collectionView 的 contentOffset = (-0.5,-0.5) <- 例如任何负值)我就会崩溃:

*** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit/UIKit-3318.16.25/UICollectionViewData.m:426

有趣的是,如果我将标题 View 属性的 frame 的 y 属性设置为 0 而不是变量 contentOffset.y(变为负数),一切正常。

有人知道为什么会这样吗?

编辑

这是一条信息更丰富的错误消息:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path ( {length = 2, path = 0 - 0}) changed from index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 0; 425.227 24); zIndex = 500; to index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 -5; 425.227 24); zIndex = 500; without invalidating the layout'

最佳答案

哇,实际上禁用了“All Exceptions”断点并得到了一个信息量更大的错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path ( {length = 2, path = 0 - 0}) changed from index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 0; 425.227 24); zIndex = 500; to index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 -5; 425.227 24); zIndex = 500; without invalidating the layout'

现在,我仍然不知道该做什么,或者去哪里

"invalidate the layout"

然后在浏览类似的问题时,我在 SO 上遇到了一个类似的问题,在那里我偶然发现了这个简单的函数: <罢工>

<罢工>
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool{
    return true
}

果然,这似乎奏效了!没有崩溃了!

编辑

实际上,这会导致 Collection View 布局在每次滚动时都失效,所以这似乎不是我正在寻找的解决方案...

编辑 #2

经过一些研究,我认为不可能创建一个在不使布局无效的情况下自行更改的补充 View (这看起来完全合乎逻辑 - 布局如何知道只更新标尺 View 而不明确这么说?)。并且更新每个卷轴上的布局太昂贵了。

所以我想我将创建一个完全独立于 Collection View 的单独 View ,并简单地监听 Collection View 的滚动委托(delegate)并根据滚动偏移调整其框架。我认为这种方法在性能方面效率更高,而且同样易于实现。

关于ios - 自定义 UICollectionViewLayout 和 float 补充标题 View 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28963916/

相关文章:

javascript - 在 iOS Safari 中禁用选择上下文菜单

iOS 混合应用程序 WKWebView 软键盘有时会覆盖输入字段

ios - 使用 indexPath 访问数组内的 UIImage 并创建空的 UIImage 数组元素

ios - 如何将 ScrollView 与 CollectionView 一起使用

ios - 如何从 iOS 应用程序使用 RTSP 将视频流发送到 WOWZA 服务器?

objective-c - 在 Cocoa Touch 中以编程方式将 View 位置设置为右上角

ios - UITabBar 在顶部还是其他?

ios - "An error occurred when accessing the keychain"

ios - Swift 中具有/不同单元格类型的可重用数据源

swift - 每行安装 2 个 Collection View 单元格(在所有设备上都相同)