假设我有三个按钮,功能是当选择按钮时我不想为该按钮添加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的不同对象,功能代码将执行三次
如何解决这个问题?
答案 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
}
}
}