如何访问自定义 CollectionView 单元格的初始值设定项?
How to access initializer for a custom CollectionView cell?
我有一个包含多个单元格的 collectionView。每个单元格都是 class:
class OuterCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var stackView: UIStackView!
override init(frame: CGRect) {
super.init(frame: frame)
print("initting")
for i in 1...30 {
let view = UIView()
view.backgroundColor = UIColor.red
view.tag = i
self.stackView.addSubview(view)
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
我正在创建我希望像这样调用其初始化程序的每个单元格:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "outerCell", for: indexPath) as! OuterCollectionViewCell
cell.backgroundColor = UIColor.gray
return cell
}
我的目的是向这个水平 stackView 添加 30 个子视图,以便显示 30 个条纹。我想在 init 中以编程方式添加这些子视图,以避免必须在情节提要中手动执行。但是现在没有调用 init 并且没有添加视图。知道为什么会这样以及如何做到这一点吗?
which I would hope calls its initializer like so
您可以希望如此,但是,正如您正确地发现的那样,您注定要失望。通过调用 dequeue
生成的单元格从未调用过它的 init(frame:)
。
一个明显的解决方案是在 cellForItemAt
中添加 30 个子视图。如果这样做,您还需要包括一个测试以确保您不会在下次重复使用该单元格时再次 添加它们。换句话说,只有当它们不存在时才添加它们。
更简单:既然您已经实现了 init(coder:)
,为什么不将您的 30 个子视图代码移到其中呢?这是一个初始化器 will 当通过出队创建一个 cell 时调用它,它 won't 当一个 cell 被调用时(显然)只是重复使用。
但是请注意,您的操作还有其他问题。正如您的代码所代表的那样,您的视图没有大小,而且堆栈视图将如何处理还远不清楚。此外,仅说 addSubview
不会导致堆栈视图对您的视图 做 任何事情。所以基本上即使您的代码运行了,我也希望您实际上看不到任何东西。但是,让我们一次过一座桥。
这里的另一个潜在问题是,如果您想将自定义方法变量添加到您的初始化程序中。对于造型之类的东西...
我最终将所有布局代码提取到它自己的方法中,该方法在 dequeueReusableCell
之后调用。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.ifNeeded(layout: .someStyle)
然后拥有一个自定义变量,您可以跟踪初始化。
var layout:Layout?
如果已经布置好了就退出
func ifNeeded(layout:Layout) {
//exit if already laid out
guard self.layout == nil else { return }
self.layout = layout
我有一个包含多个单元格的 collectionView。每个单元格都是 class:
class OuterCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var stackView: UIStackView!
override init(frame: CGRect) {
super.init(frame: frame)
print("initting")
for i in 1...30 {
let view = UIView()
view.backgroundColor = UIColor.red
view.tag = i
self.stackView.addSubview(view)
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
我正在创建我希望像这样调用其初始化程序的每个单元格:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "outerCell", for: indexPath) as! OuterCollectionViewCell
cell.backgroundColor = UIColor.gray
return cell
}
我的目的是向这个水平 stackView 添加 30 个子视图,以便显示 30 个条纹。我想在 init 中以编程方式添加这些子视图,以避免必须在情节提要中手动执行。但是现在没有调用 init 并且没有添加视图。知道为什么会这样以及如何做到这一点吗?
which I would hope calls its initializer like so
您可以希望如此,但是,正如您正确地发现的那样,您注定要失望。通过调用 dequeue
生成的单元格从未调用过它的 init(frame:)
。
一个明显的解决方案是在 cellForItemAt
中添加 30 个子视图。如果这样做,您还需要包括一个测试以确保您不会在下次重复使用该单元格时再次 添加它们。换句话说,只有当它们不存在时才添加它们。
更简单:既然您已经实现了 init(coder:)
,为什么不将您的 30 个子视图代码移到其中呢?这是一个初始化器 will 当通过出队创建一个 cell 时调用它,它 won't 当一个 cell 被调用时(显然)只是重复使用。
但是请注意,您的操作还有其他问题。正如您的代码所代表的那样,您的视图没有大小,而且堆栈视图将如何处理还远不清楚。此外,仅说 addSubview
不会导致堆栈视图对您的视图 做 任何事情。所以基本上即使您的代码运行了,我也希望您实际上看不到任何东西。但是,让我们一次过一座桥。
这里的另一个潜在问题是,如果您想将自定义方法变量添加到您的初始化程序中。对于造型之类的东西...
我最终将所有布局代码提取到它自己的方法中,该方法在 dequeueReusableCell
之后调用。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.ifNeeded(layout: .someStyle)
然后拥有一个自定义变量,您可以跟踪初始化。
var layout:Layout?
如果已经布置好了就退出
func ifNeeded(layout:Layout) {
//exit if already laid out
guard self.layout == nil else { return }
self.layout = layout