在 UICollectionViewCell 中使用 Storyboard 的自动布局约束
Using Autolayout constraints from Storyboard in UICollectionViewCell
我正在为我的 UICollectionView
使用自定义 UICollectionViewCell
class。我必须在自定义 class 中使用 addSubview,因为我使用的是 FirebaseUI-iOS。这是我的 MessageCollectionViewCell 的样子:
import Foundation
import UIKit
class MessageCollectionViewCell: UICollectionViewCell {
@IBOutlet var messageContainerView: UIView?
@IBOutlet var messageText: UILabel?
@IBOutlet var messageDisplayName: UILabel?
@IBOutlet var messageUserImage: UIImageView?
@IBOutlet var messageUserImageOverlay: UIView?
override init(frame: CGRect) {
super.init(frame: frame)
// Custom initialization code for label
let size = self.contentView.frame.size
let frame = CGRectMake(0.0, 0.0, size.width, size.height)
self.messageContainerView = UIView(frame: frame)
self.messageUserImageOverlay = UIView(frame: frame)
self.messageText = UILabel(frame: frame)
self.messageDisplayName = UILabel(frame: frame)
self.messageContainerView!.addSubview(self.messageUserImageOverlay!)
self.messageContainerView!.addSubview(self.messageText!)
self.messageContainerView!.addSubview(self.messageDisplayName!)
self.contentView.addSubview(messageContainerView!)
}
required init(coder aDecoder: NSCoder) {
println("Init")
super.init(coder: aDecoder)
}
}
我想使用的 Storyboard 文件中有约束,但是当我使用 addSubview 时,我的约束没有被使用。无论如何我可以使用 addSubview() 并仍然保持约束吗?我知道我可以通过编程方式添加它,但我希望使用我已经在 Storyboard 中设置的约束。
此问题是由于 FirebaseUI“FirebaseCollectionViewDataSource”如何注册它的 classes。我认为不可能像这样实例化 class 并像您所要求的那样从 XIB 获取自动布局属性,但是可以通过修复我们对原型单元格的处理来解决问题。
这里的问题是我们要注册单元格 reuseIdentifier 两次:一次在故事板中,一次在代码中(FirebaseCollectionViewDataSource
必须这样做才能使单元格出队)。由于我们将我们的第二个称为第二个,它会覆盖第一个,这意味着 none 您的网点已填充,布局很奇怪等。这意味着您必须像使用常规子[=一样设置它们51=]es 而不是 XIB。您在这里可以做的最快的事情就是使用 XIB 而不是原型单元(它只是情节提要中的 XIB)。那么,我们如何支持 FirebaseUI + 原型单元...
简短的回答是,由于 Apple 的 UICollectionView
设计,目前无法使用此功能。
与 UITableView
不同,它可以像我们在 FirebaseTableViewDataSource
here, UICollectionView
没有提供类似的方法,它只给出:
func dequeueReusableCellWithReuseIdentifier(_ identifier: String,
forIndexPath indexPath: NSIndexPath!) -> AnyObject
鉴于此方法需要一个 indexPath
因为它 有 到 return 一个非零对象,它会抛出一个 NSInternalInconsistencyException
当我们尝试在初始化时读取任意对象时(因为不存在可供它读取的项目)。此外,似乎没有任何方法可以通过编程方式检查 reuseIdentifier
是否正在使用。这给我们留下了一些选择:
- 建议人们不要使用原型单元,而是使用自定义子classes 或 XIB 并将它们连接起来。情节提要和原型单元感觉有点脆弱(主要是出于这样的原因),但绝对容易对他们有用。
- 从
FirebaseCollectionViewDataSource
中提取 -registerClass: forReuseIdentifier:
调用,尽管这意味着 FirebaseTableViewDataSource
也应该更改(即使它可以工作)并让开发人员明确调用它(或者在使用 Storyboard 的情况下不是)。
- 将故事板的参数添加到初始化调用,该参数仍会保留
reuseIdentifier
以出列单元格,但不会注册 class。
- 尝试使单元格出列,捕获
NSException
,注册 class 并重试。这行得通,但它仍然抛出异常并在运行循环中添加了更多代码(我们必须用我们知道最多会失败一次的 try-catch 包装调用)。
我个人的偏好是 1,但原型单元的价值主张足够高,3 可能是该库的最佳选择。我宁愿不做 2,因为小区注册是一个足够困难的问题。
目前,我建议使用 XIB 而不是原型单元,或者等待我们选择上述解决方案之一(我们可以很快发布一个版本来解决问题)。
我正在为我的 UICollectionView
使用自定义 UICollectionViewCell
class。我必须在自定义 class 中使用 addSubview,因为我使用的是 FirebaseUI-iOS。这是我的 MessageCollectionViewCell 的样子:
import Foundation
import UIKit
class MessageCollectionViewCell: UICollectionViewCell {
@IBOutlet var messageContainerView: UIView?
@IBOutlet var messageText: UILabel?
@IBOutlet var messageDisplayName: UILabel?
@IBOutlet var messageUserImage: UIImageView?
@IBOutlet var messageUserImageOverlay: UIView?
override init(frame: CGRect) {
super.init(frame: frame)
// Custom initialization code for label
let size = self.contentView.frame.size
let frame = CGRectMake(0.0, 0.0, size.width, size.height)
self.messageContainerView = UIView(frame: frame)
self.messageUserImageOverlay = UIView(frame: frame)
self.messageText = UILabel(frame: frame)
self.messageDisplayName = UILabel(frame: frame)
self.messageContainerView!.addSubview(self.messageUserImageOverlay!)
self.messageContainerView!.addSubview(self.messageText!)
self.messageContainerView!.addSubview(self.messageDisplayName!)
self.contentView.addSubview(messageContainerView!)
}
required init(coder aDecoder: NSCoder) {
println("Init")
super.init(coder: aDecoder)
}
}
我想使用的 Storyboard 文件中有约束,但是当我使用 addSubview 时,我的约束没有被使用。无论如何我可以使用 addSubview() 并仍然保持约束吗?我知道我可以通过编程方式添加它,但我希望使用我已经在 Storyboard 中设置的约束。
此问题是由于 FirebaseUI“FirebaseCollectionViewDataSource”如何注册它的 classes。我认为不可能像这样实例化 class 并像您所要求的那样从 XIB 获取自动布局属性,但是可以通过修复我们对原型单元格的处理来解决问题。
这里的问题是我们要注册单元格 reuseIdentifier 两次:一次在故事板中,一次在代码中(FirebaseCollectionViewDataSource
必须这样做才能使单元格出队)。由于我们将我们的第二个称为第二个,它会覆盖第一个,这意味着 none 您的网点已填充,布局很奇怪等。这意味着您必须像使用常规子[=一样设置它们51=]es 而不是 XIB。您在这里可以做的最快的事情就是使用 XIB 而不是原型单元(它只是情节提要中的 XIB)。那么,我们如何支持 FirebaseUI + 原型单元...
简短的回答是,由于 Apple 的 UICollectionView
设计,目前无法使用此功能。
与 UITableView
不同,它可以像我们在 FirebaseTableViewDataSource
here, UICollectionView
没有提供类似的方法,它只给出:
func dequeueReusableCellWithReuseIdentifier(_ identifier: String,
forIndexPath indexPath: NSIndexPath!) -> AnyObject
鉴于此方法需要一个 indexPath
因为它 有 到 return 一个非零对象,它会抛出一个 NSInternalInconsistencyException
当我们尝试在初始化时读取任意对象时(因为不存在可供它读取的项目)。此外,似乎没有任何方法可以通过编程方式检查 reuseIdentifier
是否正在使用。这给我们留下了一些选择:
- 建议人们不要使用原型单元,而是使用自定义子classes 或 XIB 并将它们连接起来。情节提要和原型单元感觉有点脆弱(主要是出于这样的原因),但绝对容易对他们有用。
- 从
FirebaseCollectionViewDataSource
中提取-registerClass: forReuseIdentifier:
调用,尽管这意味着FirebaseTableViewDataSource
也应该更改(即使它可以工作)并让开发人员明确调用它(或者在使用 Storyboard 的情况下不是)。 - 将故事板的参数添加到初始化调用,该参数仍会保留
reuseIdentifier
以出列单元格,但不会注册 class。 - 尝试使单元格出列,捕获
NSException
,注册 class 并重试。这行得通,但它仍然抛出异常并在运行循环中添加了更多代码(我们必须用我们知道最多会失败一次的 try-catch 包装调用)。
我个人的偏好是 1,但原型单元的价值主张足够高,3 可能是该库的最佳选择。我宁愿不做 2,因为小区注册是一个足够困难的问题。
目前,我建议使用 XIB 而不是原型单元,或者等待我们选择上述解决方案之一(我们可以很快发布一个版本来解决问题)。