无法从 UITextField 中删除 CALayer
Unable to remove a CALayer from UITextField
所以,我有这个自定义 UITextField
并且我有两种方法来添加 CALayer
和删除 CALayer
但是删除不起作用。
@IBDesignable class AppTextField : UITextField {
private let bottomLine = CALayer()
override func layoutSubviews() {
self.font = .systemFont(ofSize: 20)
self.addBottomLine()
self.clearButtonMode = .unlessEditing
super.layoutSubviews()
}
func removeBttomLine() {
bottomLine.removeFromSuperlayer()
}
private func addBottomLine() {
bottomLine.frame = CGRect(origin: CGPoint(x: 0, y: self.frame.height + 4), size: CGSize(width: self.frame.width, height: 1))
bottomLine.backgroundColor = UIColor.init(hexString: "#DCCFCA")?.cgColor
self.borderStyle = .none
self.layer.addSublayer(bottomLine)
}
}
原因可能是因为 layoutSubviews
方法被多次调用并且层被多次添加。如果您使用故事板或使用 init(frame:)
或自定义 init
方法,请尝试将 addBottomLine
方法移动到 required init?(coder:)
方法,无论哪个只被调用一次。这是一个例子:
@IBDesignable class AppTextField : UITextField {
required init?(coder: NSCoder) {
super.init(coder: coder)
addBottomLine()
}
}
您在 layoutSubviews()
中唯一应该做的就是根据需要更新帧。
当字段 NOT 正在编辑时,这将显示红线,并且当字段 IS 正在编辑:
@IBDesignable class AppTextField : UITextField {
private let bottomLine = CALayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
self.font = .systemFont(ofSize: 20)
self.backgroundColor = .white
self.clearButtonMode = .unlessEditing
self.borderStyle = .none
bottomLine.backgroundColor = UIColor.red.cgColor
addBottomLine()
}
override func layoutSubviews() {
super.layoutSubviews()
var r = bounds
r.origin.y = bounds.maxY
r.size.height = 4.0
bottomLine.frame = r
}
func removeBottomLine() {
bottomLine.removeFromSuperlayer()
}
private func addBottomLine() {
self.layer.addSublayer(bottomLine)
}
override func resignFirstResponder() -> Bool {
super.resignFirstResponder()
addBottomLine()
return true
}
override func becomeFirstResponder() -> Bool {
super.becomeFirstResponder()
removeBottomLine()
return true
}
}
您在添加方法中做了 3 件事:
- 调整框架
- 设置颜色
- 添加为子层
并且因为您是从 layoutSubviews
调用它的,所以它被调用了多次,并且您最终添加了多个图层,这就是为什么调用 remove 似乎不起作用的原因。
要使此代码正常工作,您应该将添加部分移至 init(withCoder
、withFrame
或两者)。您可以通过设置颜色加入它,因为它可以完成一次。下一部分是调整 layoutSubviews
中的框架,这是必需的,因为图层无法进入自动布局。最后,您将进行创建、添加为子层并设置在初始化时调用一次的部分,并在布局过程中调整多次调用。现在在调用一次时删除 - 这次它会产生可见的效果。
所以,我有这个自定义 UITextField
并且我有两种方法来添加 CALayer
和删除 CALayer
但是删除不起作用。
@IBDesignable class AppTextField : UITextField {
private let bottomLine = CALayer()
override func layoutSubviews() {
self.font = .systemFont(ofSize: 20)
self.addBottomLine()
self.clearButtonMode = .unlessEditing
super.layoutSubviews()
}
func removeBttomLine() {
bottomLine.removeFromSuperlayer()
}
private func addBottomLine() {
bottomLine.frame = CGRect(origin: CGPoint(x: 0, y: self.frame.height + 4), size: CGSize(width: self.frame.width, height: 1))
bottomLine.backgroundColor = UIColor.init(hexString: "#DCCFCA")?.cgColor
self.borderStyle = .none
self.layer.addSublayer(bottomLine)
}
}
原因可能是因为 layoutSubviews
方法被多次调用并且层被多次添加。如果您使用故事板或使用 init(frame:)
或自定义 init
方法,请尝试将 addBottomLine
方法移动到 required init?(coder:)
方法,无论哪个只被调用一次。这是一个例子:
@IBDesignable class AppTextField : UITextField {
required init?(coder: NSCoder) {
super.init(coder: coder)
addBottomLine()
}
}
您在 layoutSubviews()
中唯一应该做的就是根据需要更新帧。
当字段 NOT 正在编辑时,这将显示红线,并且当字段 IS 正在编辑:
@IBDesignable class AppTextField : UITextField {
private let bottomLine = CALayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
self.font = .systemFont(ofSize: 20)
self.backgroundColor = .white
self.clearButtonMode = .unlessEditing
self.borderStyle = .none
bottomLine.backgroundColor = UIColor.red.cgColor
addBottomLine()
}
override func layoutSubviews() {
super.layoutSubviews()
var r = bounds
r.origin.y = bounds.maxY
r.size.height = 4.0
bottomLine.frame = r
}
func removeBottomLine() {
bottomLine.removeFromSuperlayer()
}
private func addBottomLine() {
self.layer.addSublayer(bottomLine)
}
override func resignFirstResponder() -> Bool {
super.resignFirstResponder()
addBottomLine()
return true
}
override func becomeFirstResponder() -> Bool {
super.becomeFirstResponder()
removeBottomLine()
return true
}
}
您在添加方法中做了 3 件事:
- 调整框架
- 设置颜色
- 添加为子层
并且因为您是从 layoutSubviews
调用它的,所以它被调用了多次,并且您最终添加了多个图层,这就是为什么调用 remove 似乎不起作用的原因。
要使此代码正常工作,您应该将添加部分移至 init(withCoder
、withFrame
或两者)。您可以通过设置颜色加入它,因为它可以完成一次。下一部分是调整 layoutSubviews
中的框架,这是必需的,因为图层无法进入自动布局。最后,您将进行创建、添加为子层并设置在初始化时调用一次的部分,并在布局过程中调整多次调用。现在在调用一次时删除 - 这次它会产生可见的效果。