I'm following Swift & the Objective-C Runtime, it works for normal methods.
I like to swizzle init method, from my understanding, init is like a class method. So I tried swizzling init as instance and class method. But it does not seem to work
I can make it work using Objective C, just wonder how to make it work in Swift
Excerpted from my gist
dispatch_once(&Static.token) {
let originalSelector = Selector("init:source:destination:")
let swizzledSelector = Selector("ftg_init:source:destination:")
let originalMethod = class_getClassMethod(self, originalSelector)
let swizzledMethod = class_getClassMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
When creating the selector for a method, you should base it off the Obj C method signature since swizzling is done using the Obj C runtime.
So the original selector should be
initWithIdentifier:source:destination:
Now this gets a little weird, since your init method is defined so that the label on the first argument is required (by having
identifier
twice), the selector you want to use is actuallyftg_initWithIdentifier:source:destination:
The only documentation I could find about it talk about the translation from Obj C to Swift but it looks like the reverse is happening from Swift to Obj C.
Next,
init...
is an instance method so you'll need to make two changes. You need to changeclass_getClassMethod
toclass_getInstanceMethod
and you need to removeclass
from yourft_init...
method.So when all is said and done, your code should look like this (which worked for me)
Here is the way of doing it in Swift 4.2 for UIImage initializer: