[移除渐变时渐变按钮崩溃

问题描述 投票:0回答:3

所以我刚开始学习Swift,但是在删除按钮渐变背景时遇到了麻烦,从技术上讲,我可以“删除”它,但是它不稳定,如果连续轻击,就会崩溃,我想这与子层没有被“安全地”删除,但我环顾四周,只是无法弄清楚。帮助和感谢!

    @IBAction func button(_ sender: UIButton) {
        sender.setTitleColor(.systemBackground, for: .selected)

        sender.isSelected = !sender.isSelected
        if sender.isSelected {
            sender.layer.borderWidth = 0
            sender.applyGradient(colors: [ #colorLiteral(red: 0.5098039216, green: 0.8431372549, blue: 0.5254901961, alpha: 1) , #colorLiteral(red: 0.3058823529, green: 0.6941176471, blue: 0.3215686275, alpha: 1) ], radius: 10)
        } else {
            sender.layer.borderWidth = 1
            sender.layer.sublayers!.remove(at: 1)   // this not stable, cause crash if trigger repeatedly
        }
    }

extension UIButton
{
    func applyGradient(colors: [CGColor], radius:CGFloat = 0, startGradient:CGPoint = CGPoint(x: 0.5, y: 0.0), endGradient:CGPoint = CGPoint(x: 0.5, y: 1.0))
    {
        let gradientLayer = CAGradientLayer()
        gradientLayer.cornerRadius = radius
        gradientLayer.colors = colors
        gradientLayer.startPoint = startGradient
        gradientLayer.endPoint = endGradient
        gradientLayer.frame = self.bounds
        self.layer.insertSublayer(gradientLayer, at: 0)
    }
}
ios swift uibutton uikit cagradientlayer
3个回答
0
投票

它崩溃是因为您正试图删除一些不存在的东西,请检查是否存在然后再尝试将其删除。方法如下:

@IBAction func button(_ sender: UIButton) {
    sender.setTitleColor(.systemBackground, for: .selected)

    sender.isSelected = !sender.isSelected
    if sender.isSelected {
        sender.layer.borderWidth = 0
        sender.applyGradient(colors: [ #colorLiteral(red: 0.5098039216, green: 0.8431372549, blue: 0.5254901961, alpha: 1) , #colorLiteral(red: 0.3058823529, green: 0.6941176471, blue: 0.3215686275, alpha: 1) ], radius: 10)
    } else {
        sender.layer.borderWidth = 1
        if sender.layer.sublayers?.count > 1 {
            sender.layer.sublayers?.remove(at: 1)
        }
    }
}

0
投票

尝试这种方法

sender.layer.sublayers?.remove(at:1)

因为使用时! -您执行了强制解包,并且如果子层为零,则将导致崩溃。甚至让我们更加安全:

if let sublayers = sender.layer.sublayers,
   !sublayers.isEmpty {
    sublayers.remove(at:1)
}

0
投票

您可以通过这种方式为您的CALayer命名,以便在删除图层之前找到它的索引:

extension UIButton {
    func applyGradient(colors: [CGColor], radius: CGFloat = 0, startGradient: CGPoint = .init(x: 0.5, y: 0), endGradient: CGPoint = .init(x: 0.5, y: 1)) {
        // check first if there is already a gradient layer to avoid adding more than one
        if let firstIndex = layer.sublayers?.firstIndex(where: {$0.name == "gradient" }), let gradientLayer = layer.sublayers?[firstIndex] as? CAGradientLayer {
            gradientLayer.cornerRadius = radius
            gradientLayer.colors = colors
            gradientLayer.startPoint = startGradient
            gradientLayer.endPoint = endGradient
            gradientLayer.frame = bounds
        // if not found create a new gradient layer
        } else {
            let gradientLayer = CAGradientLayer()
            gradientLayer.name = "gradient"
            gradientLayer.cornerRadius = radius
            gradientLayer.colors = colors
            gradientLayer.startPoint = startGradient
            gradientLayer.endPoint = endGradient
            gradientLayer.frame = bounds
            layer.insertSublayer(gradientLayer, at: 0)
        }
    }
}

@IBAction func button(_ sender: UIButton) {
    sender.setTitleColor(.systemBackground, for: .selected)
    sender.isSelected.toggle()
    if sender.isSelected {
        sender.layer.borderWidth = 0
        sender.applyGradient(colors: [ #colorLiteral(red: 0.5098039216, green: 0.8431372549, blue: 0.5254901961, alpha: 1) , #colorLiteral(red: 0.3058823529, green: 0.6941176471, blue: 0.3215686275, alpha: 1) ], radius: 10)
    } else {
        sender.layer.borderWidth = 1
        if let firstIndex = sender.layer.sublayers?.firstIndex(where: {$0.name == "gradient" }) {
            sender.layer.sublayers?.remove(at: firstIndex)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.