Hi there =) I was just faced with a design problem where I need to (essentially) do the following:
I want to inject a bit of code on viewWillAppear:
of any UIViewController
subclass that conforms to a protocol MyProtocol
. Explained in code:
protocol MyProtocol
{
func protocolFunction() {
//do cool stuff...
}
}
extension UIViewController where Self: MyProtocol //<-----compilation error
{
public override class func initialize()
{
//swizzling stuff switching viewWillAppear(_: Bool) with xxx_viewWillAppear(animated: Bool)
}
// MARK: - Swizzling
func xxx_viewWillAppear(animated: Bool)
{
self.xxx_viewWillAppear(animated)
//invoke APIs from
self.protocolFunction() // MyProtocol APIs
let viewLoaded = self.isViewLoaded // UIViewController APIs
}
}
The main issue here is that I need to 2 two things in the UIVIewController
extension:
MyProtocol
and UIViewController
API'sUIViewController
method initialize()
in order to be able to swizzle viewWillAppear:
These 2 capabilities seem incompatible (as of Swift 3) because:
extension UIViewController where Self: MyProtocol
)extension MyProtocol where Self: UIViewController
but we CAN'T override methods from a class in a protocol extension, meaning we can't public override class func initialize()
which is needed for swizzling.So I was wondering if there's somebody out there who can offer a Swifty solution to this problem I'm facing? =)
Thanks in advance!!
You were near the solution. Just need to make it other way around. Extend protocol only if its part of UIViewController.
protocol MyProtocol
{
func protocolFunction() {
//do cool stuff...
}
}
extension MyProtocol where Self: UIViewController {
public override class func initialize()
{
//swizzling stuff switching viewWillAppear(_: Bool) with xxx_viewWillAppear(animated: Bool)
}
// MARK: - Swizzling
func xxx_viewWillAppear(animated: Bool)
{
self.xxx_viewWillAppear(animated)
//invoke APIs from
self.protocolFunction() // MyProtocol APIs
let viewLoaded = self.isViewLoaded // UIViewController APIs
}
}