There are several ways you could reorganize your code. For example, you could make add a convenience init
to UIButton
:
extension UIButton {
fileprivate convenience init(drawButtonWithTarget target: Any?, action: Selector) {
self.init()
setImage(UIImage(named: "pen")?.withRenderingMode(.alwaysTemplate), for: .normal)
imageView?.tintColor = .white
imageView?.layer.shadowColor = UIColor.black.cgColor
imageView?.layer.shadowOffset = CGSize(width: 0, height: 2)
imageView?.layer.shadowOpacity = 1
addTarget(target, action: action, for: .touchUpInside)
translatesAutoresizingMaskIntoConstraints = false
}
}
Then creating drawButton
looks like this:
let drawButton = UIButton(drawButtonWithTarget: self, action: #selector(pen))
Or you could give UIButton
a convenience init
that takes a closure to configure the button. I do it like this:
protocol Withable {
init()
}
extension Withable {
init(with body: (inout Self) -> ()) {
self.init()
body(&self)
}
}
extension UIButton: Withable { }
This lets you shorten the definition of drawButton
slightly:
let drawButton = UIButton {
$0.setImage(UIImage(named: "pen")?.withRenderingMode(.alwaysTemplate), for: .normal)
$0.imageView?.tintColor = .white
$0.imageView?.layer.shadowColor = UIColor.black.cgColor
$0.imageView?.layer.shadowOffset = CGSize(width: 0, height: 2)
$0.imageView?.layer.shadowOpacity = 1
$0.addTarget(self, action: #selector(pen), for: .touchUpInside)
$0.translatesAutoresizingMaskIntoConstraints = false
}
If you're setting a lot of layer shadows, you might want to factor out that code. Here's one way:
struct LayerShadow {
var opacity: Float
var radius: CGFloat
var offset: CGSize
var color: UIColor?
var path: CGPath?
init(opacity: Float = 0, radius: CGFloat = 3, offset: CGSize = CGSize(width: 0, height: -3), color: UIColor? = .black, path: CGPath? = nil) {
self.opacity = opacity
self.radius = radius
self.offset = offset
self.color = color
self.path = path
}
}
extension CALayer {
var shadow: LayerShadow {
get {
return .init(opacity: shadowOpacity, radius: shadowRadius, offset: shadowOffset, color: shadowColor.map { UIColor(cgColor: $0) }, path: shadowPath)
}
set {
shadowOpacity = shadow.opacity
shadowRadius = shadow.radius
shadowOffset = shadow.offset
shadowColor = shadow.color?.cgColor
shadowPath = shadow.path
}
}
}
Then you can reduce setting the shadow to this line:
imageView?.layer.shadow = .init(opacity: 1, offset: .init(width: 0, height: 2))