Сбой кнопки градиента при удалении градиента - PullRequest
0 голосов
/ 29 мая 2020

Итак, я новичок в изучении 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)
    }
}

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Вы можете дать своему 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 gradientLayer = layer.sublayers?.first(where: {$0.name == "gradient" }) 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)
        }
    }
}
0 голосов
/ 29 мая 2020

Он вылетает из-за того, что вы пытаетесь удалить что-то, чего нет, проверьте, есть ли оно, а затем попробуйте удалить его. Вот как:

@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)
        }
    }
}
...