我仍在提高iOS(Swift)的编程技巧。今天我正在考虑以一种好的方式创建一个UIView子类。我想创建自定义视图:
我知道init(withFrame)
init()
init(withDecoder)
prepareForInterfacebuilder()
等方法,但我不知道如何使用它们来最大限度地减少代码冗余。
例如,这是我的自定义UIButton
:
import UIKit
@IBDesignable
class SecurityButton: UIButton {
@IBInspectable
var color: UIColor = UIColor.black {
didSet {
setTitleColor(color, for: .normal)
contentEdgeInsets = UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)
layer.borderWidth = 1.0
layer.borderColor = color.cgColor
layer.cornerRadius = 6.0
}
}
}
它运作良好,但我知道每当我设置一个新颜色时contentEdgeInsets = UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)
layer.cornerRadius = 6.0
layer.borderWidth = 1.0
都会被调用。我应该在哪里放置此自定义设置以保持对自定义视图的要求?
我不寻找修复我的例子。我正在寻找一个初始化自定义视图的好地方。假设您需要执行一些耗时的操作,但只需要创建视图。
答案 0 :(得分:1)
您缺少功能
self.setNeedsDisplay()
您的代码应如下所示
import UIKit
@IBDesignable
class SecurityButton: UIButton {
@IBInspectable
var color: UIColor = UIColor.black {
didSet {
setTitleColor(color, for: .normal)
contentEdgeInsets = UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)
layer.borderWidth = 1.0
layer.borderColor = color.cgColor
layer.cornerRadius = 6.0
self.setNeedsDisplay()
}
}
}
这将调用将更新故事板视图的draw函数。 该函数应在didSet中作为last调用。现在它将在您设置颜色后显示。
我测试了它,在我在故事板中设置值颜色后,它在xcode中适用于我。
如果你想要它总是画画,不仅当你通过督察设置一个颜色时你可以使用draw(rect)函数它将会看起来如下
import UIKit
@IBDesignable
class SecurityButton: UIButton {
@IBInspectable
var color: UIColor = UIColor.black
override func draw(_ rect: CGRect) {
setTitleColor(color, for: .normal)
contentEdgeInsets = UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)
layer.borderWidth = 1.0
layer.borderColor = color.cgColor
layer.cornerRadius = 6.0
setNeedsDisplay()
}
}
这将始终绘制边框,不仅仅是在界面检查器中设置时。
答案 1 :(得分:1)
您可以创建“自定义初始化”功能来处理设置任务。
所以,例如:
import UIKit
@IBDesignable
class SecurityButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override func awakeFromNib() {
super.awakeFromNib()
commonInit()
}
func commonInit() {
layer.borderWidth = 1.0
layer.borderColor = color.cgColor
layer.cornerRadius = 6.0
_contentEdgeInsets = UIEdgeInsets(top: 0.0, left: 8.0, bottom: 0.0, right: 8.0)
updateEdgeInsets()
}
private var _contentEdgeInsets: UIEdgeInsets = UIEdgeInsets.zero {
didSet { updateEdgeInsets() }
}
override public var contentEdgeInsets: UIEdgeInsets {
get { return super.contentEdgeInsets }
set { _contentEdgeInsets = newValue }
}
private func updateEdgeInsets() {
let initialEdgeInsets = contentEdgeInsets
let t = _contentEdgeInsets.top + initialEdgeInsets.top
let l = _contentEdgeInsets.left + initialEdgeInsets.left
let b = _contentEdgeInsets.bottom + initialEdgeInsets.bottom
let r = _contentEdgeInsets.right + initialEdgeInsets.right
super.contentEdgeInsets = UIEdgeInsets(top: t, left: l, bottom: b, right: r)
}
@IBInspectable
var color: UIColor = UIColor.black {
didSet {
setTitleColor(color, for: .normal)
}
}
}
修改:自定义contentEdgeInsets
的处理方式与大多数其他属性的处理方式略有不同。
@KamilHarasimowicz - 您的“问题编辑”声明“我不寻找修复我的示例。我正在寻找一个初始化自定义视图的好地方。” ...
我的初步答案就是这样 - 它显示了初始化自定义视图的位置。
但是,由于您的评论“storyboard不会在您的解决方案中呈现contentEdgeInsets”表明您确实 DO 希望修复您的示例(否则你自己就修好了),我已经编辑了我的答案。