Как динамически обновлять размеры CAGradientLayer?
Изменение размеров CALayer'a лежит полностью на его пользователе.
Поэтому вам нужно при каждом изменении frame у вью, менять положиние / размер слоя
Пример:class MyView: UIView {
    let gradient: CALayer 
    ...
    override func layoutSubviews() {
        super.layoutSubviews()
        gradient.frame = self.bounds
    }
}
Если прям очень хочется через экстеншн, то примерно так:private var gradientPropertyKey: UInt8 = 0
extension UIView {
    func addNiceGradient() {
        let gradient =  < тут ваш слой >
        layer.addSublayer(gradient)
        let observation = layer.observe(\.bounds) { [weak gradient] layer, _ in
            gradient?.frame = layer.bounds
        }
        objc_setAssociatedObject(self, &gradientPropertyKey, observation, .OBJC_ASSOCIATION_RETAIN)
    }
}
Но будет работать хуже, да и уверены что хотите в ObjC Runtime без причины лезть?
А если поставить у под слоя градиента больше площадь заливки а у кнопки или под слоя добавить masksToBounds = true?