在使用自定义 UITableViewCell 时解决没有自定义 init 方法的问题
Working around not having a custom init method when using a custom UITableViewCell
如何解决在设置自定义 UITableViewCell
时无法使用自定义 init
方法的问题?我已经看到 ,但是,我正在添加我想在我的 init
方法中覆盖的约束。我需要添加一个格式不同的文本字段,例如数字.
我试过从我的 UITableViewCell
class 继承并在我的 init
方法中设置样式枚举,但我无法在调用 super.init
之前设置它.
class LabelIntegerTextfieldTableViewCell: LabelTextfieldTableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
{
super.textFieldStyle = .Integer
// 'self' used in property access 'textFieldStyle' before 'super.init' call
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
open class LabelTextfieldTableViewCell: UITableViewCell
{
public var label = UILabel()
public var textField = UITextField()
public var textFieldStyle = eTextfieldStyle.Integer
override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
switch textFieldStyle
{
case .Integer:
textField.contentVerticalAlignment = .center
textField.textAlignment = .right
textField.keyboardType = .numberPad
// snip
if (textFieldStyle == .MediumText)
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(==label)]-|",
options: [], metrics: nil, views: viewsDict))
}
else
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(100)]-|",
options: [], metrics: nil, views: viewsDict))
}
我知道在其他 SO post 中提到使用 update
方法,但正如我所说,我不想删除约束和其他部分。
您尝试实现的行为实际上并不是一个好的设计,因为 UITableViewCell
被重复使用了。所以你不应该依赖于在 init
方法中配置它们的外观。例如,您可以实例化一个传递 Integer
样式的单元格,稍后,如果您将单元格设置为具有不同的样式,则会出现不一致的状态(因为您将看到的内容不会反映您的设置) .话虽这么说,您应该考虑使用更具反应性的方法,在这种方法中,您的单元格会根据设置的内容,无论何时设置。在你的情况下,你可能想看看 didSet
属性 观察者。你会有类似下面的东西:
public var textFieldStyle = eTextfieldStyle.Integer {
didSet {
updateAppearance()
}
}
func updateAppearance() {
switch textFieldStyle {
case .Integer:
// ...
}
}
编辑
而在您的 tableView(_:cellForRowAt:)
中,您只需设置适当的样式,如下所示:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "your cell identifier goes here", for: indexPath)
// Here you obtain the proper style depending on the index path, for instance:
if indexPath.row == 0 {
cell.textFieldStyle = .Integer
} else {
cell.textFieldStyle = . MediumText
}
return cell
}
由于单元格被重复使用并且很可能通过 dequeueReusableCell(reuseIdentifier:indexPath:)
创建,您通常不需要在 init
方法中执行任何特定操作。
在你的情况下,我建议你创建一个函数,根据 textFieldStyle
属性 配置你的单元格(删除任何以前的配置,如必要时的约束;这可能意味着你需要在属性中保留对这些约束的引用)。
你可以在两个地方调用这个函数:
- 在
awakeFromNib
中(如果您使用故事板)或 init(style:reuseIdentifier:) if you aren't, to configure the cell according to the default value of
textFieldStyle`
- 在来自
textFieldStyle
本身的 didSet
观察者中。
例如
open class LabelTextfieldTableViewCell: UITableViewCell
{
public var label = UILabel()
public var textField = UITextField()
public var textFieldStyle = eTextfieldStyle.Integer {
didSet {
self.configureCell()
}
}
override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.configureCell()
}
override func awakeFromNib() {
super.awakeFromNib()
self.configureCell()
}
private func configureCell() {
switch textFieldStyle {
case .Integer:
textField.contentVerticalAlignment = .center
textField.textAlignment = .right
textField.keyboardType = .numberPad
// snip
if (textFieldStyle == .MediumText)
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(==label)]-|",
options: [], metrics: nil, views: viewsDict))
}
else
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(100)]-|",
options: [], metrics: nil, views: viewsDict))
}
在您的 cellForRow(at:)
中,您只需将可重复使用的单元格出队并设置其类型:
cell.textFieldStyle = .MediumText
另一种方法是创建三个不同的子类并将它们与不同的重用标识符相关联。然后就可以在awakeFromNib
/init
配置一次cell
如何解决在设置自定义 UITableViewCell
时无法使用自定义 init
方法的问题?我已经看到 init
方法中覆盖的约束。我需要添加一个格式不同的文本字段,例如数字.
我试过从我的 UITableViewCell
class 继承并在我的 init
方法中设置样式枚举,但我无法在调用 super.init
之前设置它.
class LabelIntegerTextfieldTableViewCell: LabelTextfieldTableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
{
super.textFieldStyle = .Integer
// 'self' used in property access 'textFieldStyle' before 'super.init' call
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
open class LabelTextfieldTableViewCell: UITableViewCell
{
public var label = UILabel()
public var textField = UITextField()
public var textFieldStyle = eTextfieldStyle.Integer
override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
switch textFieldStyle
{
case .Integer:
textField.contentVerticalAlignment = .center
textField.textAlignment = .right
textField.keyboardType = .numberPad
// snip
if (textFieldStyle == .MediumText)
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(==label)]-|",
options: [], metrics: nil, views: viewsDict))
}
else
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(100)]-|",
options: [], metrics: nil, views: viewsDict))
}
我知道在其他 SO post 中提到使用 update
方法,但正如我所说,我不想删除约束和其他部分。
您尝试实现的行为实际上并不是一个好的设计,因为 UITableViewCell
被重复使用了。所以你不应该依赖于在 init
方法中配置它们的外观。例如,您可以实例化一个传递 Integer
样式的单元格,稍后,如果您将单元格设置为具有不同的样式,则会出现不一致的状态(因为您将看到的内容不会反映您的设置) .话虽这么说,您应该考虑使用更具反应性的方法,在这种方法中,您的单元格会根据设置的内容,无论何时设置。在你的情况下,你可能想看看 didSet
属性 观察者。你会有类似下面的东西:
public var textFieldStyle = eTextfieldStyle.Integer {
didSet {
updateAppearance()
}
}
func updateAppearance() {
switch textFieldStyle {
case .Integer:
// ...
}
}
编辑
而在您的 tableView(_:cellForRowAt:)
中,您只需设置适当的样式,如下所示:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "your cell identifier goes here", for: indexPath)
// Here you obtain the proper style depending on the index path, for instance:
if indexPath.row == 0 {
cell.textFieldStyle = .Integer
} else {
cell.textFieldStyle = . MediumText
}
return cell
}
由于单元格被重复使用并且很可能通过 dequeueReusableCell(reuseIdentifier:indexPath:)
创建,您通常不需要在 init
方法中执行任何特定操作。
在你的情况下,我建议你创建一个函数,根据 textFieldStyle
属性 配置你的单元格(删除任何以前的配置,如必要时的约束;这可能意味着你需要在属性中保留对这些约束的引用)。
你可以在两个地方调用这个函数:
- 在
awakeFromNib
中(如果您使用故事板)或init(style:reuseIdentifier:) if you aren't, to configure the cell according to the default value of
textFieldStyle` - 在来自
textFieldStyle
本身的didSet
观察者中。
例如
open class LabelTextfieldTableViewCell: UITableViewCell
{
public var label = UILabel()
public var textField = UITextField()
public var textFieldStyle = eTextfieldStyle.Integer {
didSet {
self.configureCell()
}
}
override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.configureCell()
}
override func awakeFromNib() {
super.awakeFromNib()
self.configureCell()
}
private func configureCell() {
switch textFieldStyle {
case .Integer:
textField.contentVerticalAlignment = .center
textField.textAlignment = .right
textField.keyboardType = .numberPad
// snip
if (textFieldStyle == .MediumText)
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(==label)]-|",
options: [], metrics: nil, views: viewsDict))
}
else
{
contentView.addConstraints(NSLayoutConstraint
.constraints(withVisualFormat:
"H:|-[label]-[textField(100)]-|",
options: [], metrics: nil, views: viewsDict))
}
在您的 cellForRow(at:)
中,您只需将可重复使用的单元格出队并设置其类型:
cell.textFieldStyle = .MediumText
另一种方法是创建三个不同的子类并将它们与不同的重用标识符相关联。然后就可以在awakeFromNib
/init