在三个按钮中同时添加/删除GradientLayer

时间:2017-05-05 10:46:29

标签: ios swift cagradientlayer

假设我有三个按钮,功能是当选择按钮时我不想为该按钮添加MygradientLayer并且想要其他两个按钮..

对于添加和删除GradientLayer,我为UIView创建了一个扩展名,如下所示:

extension UIView {

    private var gradientLayer : CAGradientLayer {

        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = self.bounds
        gradientLayer.colors = arrButtonColors.map({$0.cgColor})
        return gradientLayer
    }

    open func applyGradientColor() {
        self.layer.insertSublayer(gradientLayer, at: 0)
    }

    open func removeGradientLayer() {

       gradientLayer.removeFromSuperlayer() --// this does't remove gradientLayer at all

       self.layer.sublayers?.removeAll() --// this will remove all the layer include UILabelLayer , that doesn't i want

      self.layer.sublayers = nil --// same effect as above(2nd condition)

    }

}

我在ViewController中的功能代码:

if view.isHidden {
            btn.applyGradientColor()
        } else  {
            btn.removeGradientLayer()
        }

我知道如果btn(Button)没有任何图层(不包括UILabelLayer)那么它会      否则不添加GradientLayer,因为我试图删除所有     首先是sublayer,甚至尝试在view.isHidden块中删除0索引处的子图层。 虽然它也行不通。

对于UIButton的不同对象,

功能代码将执行三次

如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您没有对之前添加的gradientLayer的引用。你必须保留它。一种方法是将其子类化并将变量保留在那里。或者您也可以使用objc_setAssociatedObject在运行时使用扩展名保留它。

以下是如何执行此操作的示例:

private var key = "gradientLayerKey"
extension UIView {
    private var gradientLayer: CAGradientLayer? {
        get {
            return objc_getAssociatedObject(self, &key) as? CAGradientLayer
        }

        set {
            objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    private var gradientLayerInstance: CAGradientLayer {
        let newGradientLayer = CAGradientLayer()
        newGradientLayer.frame = self.bounds
        newGradientLayer.colors = arrButtonColors.map { $0.cgColor }
        return newGradientLayer
    }

    open func applyGradientColor() {
        gradientLayer?.removeFromSuperLayer()
        // next line sets gradientLayer and retains it.
        gradientLayer = gradientLayerInstance
        self.layer.insertSublayer(gradientLayer, at: 0)
    }

    open func removeGradientLayer() {
        gradientLayer?.removeFromSuperlayer()
    }
}

答案 1 :(得分:0)

您已将gradientLayer作为计算属性。这意味着每次阅读该属性时都会获得一个新图层。把它变成一个普通的财产。

这可能意味着你必须使用UIButton的子类,而不是扩展。或者,让你的删除代码循环遍历所有子图层,只删除渐变图层。

编辑:

查找和删除渐变图层的代码可能如下所示:

open func removeGradientLayer() {
   if let layers = layer.subLayers {
     for aLayer in layers {
       if aLayer is CAGradientLayer {
         aLayer.removeFromSuperlayer
         break
       }
   }
}