Skip to content

Instantly share code, notes, and snippets.

@tettoffensive
Created April 7, 2017 23:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tettoffensive/ce6ae1fdc540e903e9242f641fd8c54c to your computer and use it in GitHub Desktop.
Save tettoffensive/ce6ae1fdc540e903e9242f641fd8c54c to your computer and use it in GitHub Desktop.
How to Swizzle what looks like an init method in Swift that's really a class method in Obj-C
typealias UIAlertActionHandler = ((UIAlertAction) -> Swift.Void)?
private struct AssociatedKeys {
static var handler = "cc_handler"
}
private let swizzling: (UIAlertAction.Type) -> () = { action in
// in swift this looks like an init, but in obj-c it's really actionWithTitle:style:handler class method
let originalSelector = #selector(UIAlertAction.init(title:style:handler:))
let swizzledSelector = #selector(UIAlertAction.action(testTitle:style:handler:)) // so swizzling an init won't work. we have to use another class method
let originalMethod = class_getClassMethod(action, originalSelector)
let swizzledMethod = class_getClassMethod(action, swizzledSelector)
method_exchangeImplementations(originalMethod, swizzledMethod)
}
extension UIAlertAction {
var handler: UIAlertActionHandler? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handler) as? UIAlertActionHandler
}
}
open override class func initialize() {
// make sure this isn't a subclass
guard self === UIAlertAction.self else {
return
}
swizzling(self)
}
// class method, rather than convenience init, because method we're swizzling with in obj-c is a class method
class func action(testTitle: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Swift.Void)? = nil) -> UIAlertAction {
let action = UIAlertAction.action(testTitle: testTitle, style: style, handler: handler)
if let handler = handler {
objc_setAssociatedObject(action, &AssociatedKeys.handler, handler, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return action
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment