【问题标题】:How to downcast custom UICollectionViewLayoutAttributes to apply() method?如何将自定义 UICollectionViewLayoutAttributes 向下转换为 apply() 方法?
【发布时间】:2018-07-16 11:28:04
【问题描述】:

我只是不知道如何在自定义单元格的 apply() 方法中访问自定义布局属性。

我必须为我的CollectionViewLayoutAtrributes 实现一个自定义布局属性,所以我对它们进行了子类化。到目前为止效果很好:

class TunedLayoutAttributes: UICollectionViewLayoutAttributes {

    var customLayoutAttributeValue: CGFloat = 1000

    override func copy(with zone: NSZone?) -> Any {
        let copy = super.copy(with: zone) as! TunedLayoutAttributes
        customLayoutAttributeValue = customLayoutAttributeValue
        return copy
    }

    override func isEqual(_ object: Any?) -> Bool {
        if let attributes = object as? TunedLayoutAttributes {
            if attributes. customLayoutAttributeValue == customLayoutAttributeValue {
                return super.isEqual (object)
            }
        }
        return false
    }
}

该值必须根据用户滚动交互动态变化。 现在我需要我的自定义单元格在来自自定义UICollectionViewLayout 类的invalidateLayout 调用之后更新它们的外观。据我所知,这通常也可以通过覆盖单元格类apply(_ layoutAttributes: UICollectionViewLayoutAttributes) 方法来完成。

通常是这样的:

override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {

    let newFrame = // calculations here. CGRect(....) 
    layoutAttributes.frame = newFrame
}




现在缺少的化学反应:

与上面的apply() 示例不同,我的新customLayoutAttributeValue(当然?)不是方法中layoutAttributes: 的一部分。

所以我尝试将 layoutAttributes 向下转换为我的自定义类,如下所示:

override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {

    let tunedLayoutAttributes = layoutAttributes as! TunedLayoutAttributes
    tunedLayoutAttributes.customLayoutAttributeValue = // calculation here. 
}

那么如何在 apply() 方法中访问 tuneLayoutAttributes? 任何帮助表示赞赏。感谢阅读!

【问题讨论】:

    标签: swift uicollectionview uicollectionviewcell uicollectionviewlayout downcast


    【解决方案1】:

    您在这里为自己提供了解决方案。 UICollectionViewLayoutAttributes(当然)不知道customLayoutAttributeValue,所以你必须转换为适当的类(TunedLayoutAttributes,在你的情况下)。

    现在,为了让apply(_:) 真正为您提供TunedLayoutAttributes 而不仅仅是简单的UICollectionViewLayoutAttributes,您需要告诉您的UICollectionViewLayout 子类在出售项目的布局属性时使用您的自定义类(TunedLayoutAttributes)在布局中。

    您可以通过在布局子类中覆盖 class var layoutAttributesClass 来做到这一点。

    请注意,如果您在布局子类中覆盖布局属性自动售货方法(layoutAttributesForElements(in:) 和朋友),则需要在此处返回 TunedLayoutAttributes 以使整个工作正常。

    另请注意,UIKit 在执行集合视图布局传递时经常在后台复制属性,因此请确保您的 copyisEqual 方法按预期工作。 (例如,传递给 apply(_:) 的属性对象不是(必然)您的布局出售的对象,而是副本。

    编辑

    正如 cmets 中所讨论的,您应该将强制转换 as! 替换为 if let as? 转换,以防止在 apply(_:) 实际通过普通 UICollectionViewLayoutAttributes 时发生崩溃。

    【讨论】:

    • 非常感谢!不知何故,我仍然无法让它工作。事实上你是对的——我的override class var layoutAttributesClass: AnyClass { return TunedLayoutAttributes.self } 被注释掉了:) 但这条线let tunedLayoutAttributes = layoutAttributes as! TunedLayoutAttributes 似乎有问题。我收到错误并崩溃:无法将“UICollectionViewLayoutAttributes”类型的值...转换为“timeline_Swift_v002.TunedLayoutAttributes”...无法将“UICollectionViewLayoutAttributes”类型的值...转换为“...TunedLayoutAttributes”。跨度>
    • 好吧,这次崩溃并不奇怪,因为你强制施法,这显然会在这里出错。我的猜测是,您在自定义布局子类中覆盖的方法不会提供实际的 TunedLayoutAttributes 而是 UICollectionViewLayoutAttributes。你能证实吗?同样,尝试在TunedLayoutAttributescopyisEqual 中添加断点,并查看控制流是否甚至到达这些断点。如果不是,您的布局类没有处理您的自定义属性类。
    • 此外,尝试将强制转换 (as!) 切换为 if let as? 转换,看看是否命中了 if 主体。这背后的原因是,也许您的 UICollectionViewCell 子类(您在其中覆盖 apply(_:) 被用于另一个上下文(可能是另一个布局对象,可能是另一个 TunedLayoutAttributes 不适用的 indexPath)实际上对 @ 有效987654352@ 在那里传递UICollectionViewLayoutAttributes
    • 太棒了!谢啦。我尝试了断点。据我了解其背后的想法,他们没有证实你的猜测。但这是强制的。 if let tunedLayoutAttributes = layoutAttributes as? TunedLayoutAttributes { ... } 是解决方案。
    • 这里的游戏规则是什么?我可以在这个帖子中将解决方案作为另一个答案发布 - 你将如何获得我的支持?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多