I am working on several custom UIControl objects that need to be created programmatically. Usually when using AutoLayout I just pass a CGRect. When using the Visual Format Language the:
override init(frame: CGRect) {
super.init(frame: frame)
updateLayer()
}
in the UIControl class is not called by the constraints method in ViewDidLoad() and the CAShapeLayers are not updated. The custom button/slider/knob, etc work but is invisible and I could update the shape as soon as it is touched. Not really helpful. How can I have a custom UIControl using VFL appear on the screen as soon as the view is loaded? This is what I would like to do:
import UIKit
class ViewController: UIViewController {
let knob = Knob()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(knob)
knob.translatesAutoresizingMaskIntoConstraints = false
let views = [
"slider": knob
]
let formatV = "V:|-[knob(300)]-|"
let formatH = "H:|-[knob(300)]-|"
let VC = NSLayoutConstraint.constraints(withVisualFormat: formatV, options: NSLayoutFormatOptions(), metrics: nil, views: views)
let HC = NSLayoutConstraint.constraints(withVisualFormat: formatH, options: NSLayoutFormatOptions(), metrics: nil, views: views)
self.view.addConstraints(VC)
self.view.addConstraints(HC)
knob.addTarget(self, action: #selector(knobRotated(_:)), for: .touchDown)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@objc func knobRotated(_ sender: Knob) {
print(sender.value)
}
}
Or what is the best approach for creating a UIControl that works both with AutoLayout and VFL?
UIControl
is a subclass of UIView
, so treat them similarly. Understanding the lifecycle of UIView
, which has a number of methods, is the key to solving your problem. Print from within them and see when and how often they fire. Below are the more common lifecycle methods used when subclassing UIView
.
class CustomButton: UIControl {
override init(frame: CGRect) {
super.init(frame: frame)
print("init")
}
override func updateConstraints() {
print("update constraints")
super.updateConstraints() // in this method, super is to be called last
}
override func layoutSubviews() {
super.layoutSubviews()
print("layout subviews")
}
}
For more reading: https://developer.apple.com/documentation/uikit/uiview