简体   繁体   中英

Extension UIButton only when conforming to a protocol

I'm trying to create several extensions for UIButton so I can add some functionality easily just by adding a protocol to a custom button. It'd be a lot easier if I didn't have to override some methods in UIButton so I'm thinking I'll have to make an extension for UIButton itself.

For example, I have several protocols my custom buttons can conform to:

protocol CustomLayer { }

protocol ButtonSound { }

So far I only managed to create an extension for UIButton without any constraints (these are simplified versions):

// Only when the button conforms to protocol CustomLayer
extension UIButton {
    override public class func layerClass() -> AnyClass { return CAShapeLayer.self }
}

// Only when the button conforms to protocol ButtonSound
extension UIButton {
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesBegan(touches, withEvent: event)

        AudioServicesPlaySystemSound(1104)
    }
}

I've read posts I can make an extension for the protocol itself with a where clause for the class UIButton :

extension CustomLayer where Self: UIButton { }

But then I can't override any methods of UIButton itself.

Other suggestions like subclassing works, but certain buttons can't have the same functionality:

class A: CustomLayer { } // Can't have ButtonSound, single subclass works
class B: ButtonSound { } // Can't have CustomLayer, single subclass works

class C: CustomLayer, ButtonSound { } // Error: multiple inheritance from classes
import Foundation

protocol BackButtonDelegate {

    func BackButtonAction(sender:UIButton)
}

class NavigationBack: UIButton
{
     var delegate : BackButtonDelegate!

    override func drawRect(rect: CGRect) {
        self.frame = CGRectMake(0, 0, 60, 60)
        self.setTitle("Back", forState: .Normal)
        self.titleLabel?.font = UIFont(name: "Helvetica",size: 12)
        self.setImage(UIImage(named: "back-arrow"), forState: .Normal)

        self.addTarget(self, action: #selector(NavigationBack.click(_:)), forControlEvents: UIControlEvents.TouchUpInside)

   }
    func click(sender:UIButton)
    {
        if delegate != nil
        {
            delegate!.BackButtonAction(sender)
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM