Reputation: 354
I am trying to extend more than one class which are UIButton and UITextField. They both have the same function where they can wiggle when I call the function. I'm trying not to repeat my code more than once. I have been attempting to use protocal that I can extend the and write the function that I want and then extend them in my classes, but the problem is in my function I have to call self, but I will get an error since self can be only called on UITextField and UIButton.
Here is my code
import UIKit
extension UIButton {
func wiggle() {
let position = "position"
let wiggleAnimation = CABasicAnimation(keyPath: position)
wiggleAnimation.duration = 0.05
wiggleAnimation.repeatCount = 5
wiggleAnimation.autoreverses = true
wiggleAnimation.fromValue = CGPoint(x: self.center.x - 4.0, y: self.center.y)
wiggleAnimation.toValue = CGPoint(x: self.center.x + 4.0, y: self.center.y)
layer.add(wiggleAnimation, forKey: position)
}
}
extension UITextField {
func wiggle() {
let position = "position"
let wiggleAnimation = CABasicAnimation(keyPath: position)
wiggleAnimation.duration = 0.05
wiggleAnimation.repeatCount = 5
wiggleAnimation.autoreverses = true
wiggleAnimation.fromValue = CGPoint(x: self.center.x - 4.0, y: self.center.y)
wiggleAnimation.toValue = CGPoint(x: self.center.x + 4.0, y: self.center.y)
layer.add(wiggleAnimation, forKey: position)
}
}
Here is what I have tried to attempt but I get an error because I am calling self.
protocol Animations {
func wiggle()
}
extension Animations {
func wiggle() {
let position = "position"
let wiggleAnimation = CABasicAnimation(keyPath: position)
wiggleAnimation.duration = 0.05
wiggleAnimation.repeatCount = 5
wiggleAnimation.autoreverses = true
wiggleAnimation.fromValue = CGPoint(x: self.center.x - 4.0, y: self.center.y)
wiggleAnimation.toValue = CGPoint(x: self.center.x + 4.0, y: self.center.y)
layer.add(wiggleAnimation, forKey: position)
}
}
extension UIButton: Animations {}
extension UITextField: Animations {}
The errors that I receive are Value of type 'Self' has no member 'center' Value of type 'Self' has no member 'center' Use of unresolved identifier 'layer'
Upvotes: 1
Views: 182
Reputation: 3785
Only UIView
has a center property. Your protocol declaration should look like this for Swift 5+:
protocol Animations: UIView {
func wiggle()
}
Care that only UIViews can conform to this protocol.
For Swift 4.x you have to use it like this:
protocol Animations {
func wiggle()
}
extension Animations where Self: UIView {
func wiggle() {
let position = "position"
let wiggleAnimation = CABasicAnimation(keyPath: position)
wiggleAnimation.duration = 0.05
wiggleAnimation.repeatCount = 5
wiggleAnimation.autoreverses = true
wiggleAnimation.fromValue = CGPoint(x: self.center.x - 4.0, y: self.center.y)
wiggleAnimation.toValue = CGPoint(x: self.center.x + 4.0, y: self.center.y)
layer.add(wiggleAnimation, forKey: position)
}
}
Upvotes: 6
Reputation: 141
The previous answer given does not actually compile using Swift 4.x, as protocols could not directly inherit from classes before Swift 5.
The correct way to write this in Swift 4.x involves providing a default implementation for your wiggle()
function only when the conforming type inherits from UIView
. The correct way to write this is:
protocol Animations {
func wiggle()
}
extension Animations where Self: UIView {
func wiggle() {
let position = "position"
let wiggleAnimation = CABasicAnimation(keyPath: position)
wiggleAnimation.duration = 0.05
wiggleAnimation.repeatCount = 5
wiggleAnimation.autoreverses = true
wiggleAnimation.fromValue = CGPoint(x: self.center.x - 4.0, y: self.center.y)
wiggleAnimation.toValue = CGPoint(x: self.center.x + 4.0, y: self.center.y)
layer.add(wiggleAnimation, forKey: position)
}
}
Upvotes: 4