I wanted to design a rounded button with a shadow for my iOS project in Swift. So I came up with the following custom button class:
import UIKit
@IBDesignable class MainButton: UIButton {
private var shadowLayer: CAShapeLayer!
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
let image = createBackgroundImage()
setBackgroundImage(image, for: UIControl.State.normal)
clipsToBounds = true
contentEdgeInsets = UIEdgeInsets(top: 5, left: 20, bottom: 5, right: 20)
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 3)
layer.shadowOpacity = 0.2
layer.shadowRadius = 6
}
func createBackgroundImage() -> UIImage {
let rect = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0)
let color = UIColor.white
color.setFill()
UIBezierPath(roundedRect: rect, cornerRadius: frame.height * 0.5).addClip()
color.setFill()
UIRectFill(rect)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
}
As soon as I set this class for a button in my Storyboard the "IBDEsignablesAgent-iOS" process takes nearly 100% of my CPU and Xcode hangs it self. This behavior makes it near impossible to debug the problem correctly.
I'm quite certain I do something in the wrong order or wrong method. But I have no clue how to solve it. Hopefully someone here can point me the right direction.
Thanks, Jens
Simply check that the size of the view actually changed:
private var lastSize: CGSize = .zero
override func layoutSubviews() {
super.layoutSubviews()
guard frame.size != lastSize else { return }
lastSize = frame.size
...
}
Creating shadows is slow and layoutSubviews
is called tens of times every second (basically, once every frame).