如何将自定义 UICollectionReusableView 用作 collection 视图的 header 部分?
How to use custom UICollectionReusableView as section header of collection view?
我已经被逼疯了几个小时,因为我无法解决这个问题。
我有一个 collection 视图,它可以有不同编号的不同部分。每个项目中的项目。对于每个部分,我需要使用不同类型的部分 header。因此,为此,我将使用 UICollectionReusableView
。但是我似乎无法通过 UINib
注册来成功使用 UICollectionReusableView
的自定义子类。
A crash happens when I downcast the reusable view to my subclass. Like:
let friendHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
withReuseIdentifier: "FriendHeaderView",
for: indexPath) as! FriendHeaderView
下面是代码片段:
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
private let viewModel = ProfileViewModel()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
// more code
collectionView.register(UINib(nibName: "FriendHeaderView", bundle: nil),
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: "FriendHeaderView")
}
}
下面是数据源实现:
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
// valid implementation
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// valid implementation
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// valid implementation
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
let friendHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FriendHeaderView", for: indexPath) as! FriendHeaderView
// *** Crash happens here *** //
return friendHeader
default:
assert(false, "Invalid element type")
}
}
}
而且我不知道为什么 collectionView(_:layout:referenceSizeForHeaderInSection:)
也需要实施。所以这里是:
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let size = CGSize(width: collectionView.bounds.width, height: 100)
return size
}
}
Okay, now come to the point: The above mentioned crash doesn't happen
at all if I don't downcast with as!
operator. Well, if I use section
header from the storyboard instead of UINib
registration, there is
no crash.
如果我需要多种类型 header,那么我不能同时使用故事板方法或不使用 down-casting 方法,因为我需要向那些 header 提供数据秒。
如何使用从 Interface Builder 构建的视图拥有多个类型 header?
我根据上面所说的做了一个demo project。如果有人感兴趣,请检查一下。
一旦您在 Xib 文件中分配了正确的 class 和标识符,它就可以正常工作。
好吧,经过更多调查和@good4pc 在接受的答案中的输入(实际上我在查看答案之前自己发现了这一点)似乎问题实际上是由于 [= 的一些不需要的问题而发生的35=]Xcode。
当我们使用 .xib
创建任何视图(最好是 UITableViewCell
或 UICollectionViewCell
)时,会自动为 .xib
中的 class 提供身份身份检查员。但 UICollectionReusableView
的情况并非如此。请参阅下面随附的屏幕截图,以便于理解。
这是一个 UICollectionViewCell
subclassed with .xib
:
这是一个 UICollectionReusableView
subclassed with .xib
:
So the key is to provide the class identity of the .xib
file which
is done from the attributes inspector.
我已经被逼疯了几个小时,因为我无法解决这个问题。
我有一个 collection 视图,它可以有不同编号的不同部分。每个项目中的项目。对于每个部分,我需要使用不同类型的部分 header。因此,为此,我将使用 UICollectionReusableView
。但是我似乎无法通过 UINib
注册来成功使用 UICollectionReusableView
的自定义子类。
A crash happens when I downcast the reusable view to my subclass. Like:
let friendHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
withReuseIdentifier: "FriendHeaderView",
for: indexPath) as! FriendHeaderView
下面是代码片段:
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
private let viewModel = ProfileViewModel()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
// more code
collectionView.register(UINib(nibName: "FriendHeaderView", bundle: nil),
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: "FriendHeaderView")
}
}
下面是数据源实现:
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
// valid implementation
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// valid implementation
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// valid implementation
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
let friendHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FriendHeaderView", for: indexPath) as! FriendHeaderView
// *** Crash happens here *** //
return friendHeader
default:
assert(false, "Invalid element type")
}
}
}
而且我不知道为什么 collectionView(_:layout:referenceSizeForHeaderInSection:)
也需要实施。所以这里是:
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let size = CGSize(width: collectionView.bounds.width, height: 100)
return size
}
}
Okay, now come to the point: The above mentioned crash doesn't happen at all if I don't downcast with
as!
operator. Well, if I use section header from the storyboard instead ofUINib
registration, there is no crash.
如果我需要多种类型 header,那么我不能同时使用故事板方法或不使用 down-casting 方法,因为我需要向那些 header 提供数据秒。
如何使用从 Interface Builder 构建的视图拥有多个类型 header?
我根据上面所说的做了一个demo project。如果有人感兴趣,请检查一下。
一旦您在 Xib 文件中分配了正确的 class 和标识符,它就可以正常工作。
好吧,经过更多调查和@good4pc 在接受的答案中的输入(实际上我在查看答案之前自己发现了这一点)似乎问题实际上是由于 [= 的一些不需要的问题而发生的35=]Xcode。
当我们使用 .xib
创建任何视图(最好是 UITableViewCell
或 UICollectionViewCell
)时,会自动为 .xib
中的 class 提供身份身份检查员。但 UICollectionReusableView
的情况并非如此。请参阅下面随附的屏幕截图,以便于理解。
这是一个 UICollectionViewCell
subclassed with .xib
:
这是一个 UICollectionReusableView
subclassed with .xib
:
So the key is to provide the class identity of the
.xib
file which is done from the attributes inspector.