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 actually
ftg_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 change class_getClassMethod
to class_getInstanceMethod
and you need to remove class
from your ft_init...
method.
So when all is said and done, your code should look like this (which worked for me)
dispatch_once(&Static.token) {
let originalSelector = Selector("initWithIdentifier:source:destination:")
let swizzledSelector = Selector("ftg_initWithIdentifier:source:destination:")
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(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);
}
}
func ftg_init(identifier identifier: String!,
source: UIViewController,
destination: UIViewController) -> UIStoryboardSegue {
return ftg_init(identifier: identifier,
source: source,
destination: destination.ftg_resolve())
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…