segunda-feira, 9 de julho de 2018

Dicas de Programação: Entendendo extensões em Swift

Extensões em Swift não são as coisas mais fáceis de se entender, mas não é um bicho de sete (7) cabeças. (se bem que bicho de sete cabeças não existe... eu acho... :P )

Extensões são, na prática, adições de métodos em classes já existentes.

Iremos a um exemplo, que isso torna as coisas mais fáceis. :)

Vamos dizer que eu precise, em meu projeto, botões que tenham, em sua característica, um fundo de cor gradiente, conforme ilustração:


Ok, neste caso, eu só tenho uma propriedade backgroundColor que coloca, ou imagem, ou uma cor sólida no botão...

Porém, eu sei que dá para fazer isso com um CAGradientLayer, adicionando esta como uma sublayer de uma UIView:

    override func viewDidAppear(_ animated: Bool) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [UIColor.yellow, UIColor.green]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 0, y: 1)
        gradientLayer.frame = CGRect(x: 0, y: 0, width: myButton.bounds.width, height:  myButton.bounds.height)
        myButton.layer.insertSublayer(gradientLayer, at: 0)
    }

Contudo, para cada botão que eu tiver na tela (ou telas) que precise de um gradiente, vou precisar usar o mesmo código...

Para evitar isso, que tal "adicionarmos" um método chamado "setGradientColors" em todos os botões (classe UIButton)?

Adicionar? Eureka! Como eu escrevi acima, é para isso que a extensão existe:

extension UIButton
{
    func setGradientColors(startColor: UIColor, endColor: UIColor) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 0, y: 1)
        gradientLayer.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height)
        gradientLayer.type = kCAGradientLayerAxial
        if let sublayers = self.layer.sublayers {
            if (sublayers.count > 0) {
                let sublayer = sublayers[0]
                if (sublayer is CAGradientLayer) {
                    sublayer.removeFromSuperlayer()
                }
            }
        }
        self.layer.insertSublayer(gradientLayer, at: 0)
        self.layoutIfNeeded()
    }
}

Agora, para cada botão que precise usar um fundo gradiente, só é preciso chamar o método "setGradientColors":

override func viewDidAppear(_ animated: Bool) {
    myButton.setGradientColors(startColor: UIColor.yellow, endColor: UIColor.green)
}

Entretanto, você pergunta: Mas se eu quiser usar em um UILabel... Vou ter que criar a mesma função para esta classe?

Sim... e não! Se você quiser usar em todas as classes que herdam de UIView (UILabel e UIButton são filhos de UIView), você pode somente trocar a extensão de UIButton para UIView:

extension UIView
{
    func setGradientColors(startColor: UIColor, endColor: UIColor) {
        ...
    }
}

Que tudo vai funcionar! :)

Legal, né? Mas, como você pode ver, extensões são poderosas e, portanto, devem, sem dúvida nenhuma, serem utilizadas com cautela. (como diz tio Ben: "Com grandes poderes....")

Até mais!

Nenhum comentário: