Skip to content

Instantly share code, notes, and snippets.

@donpironet
Created June 29, 2016 10:56
Show Gist options
  • Save donpironet/f5ce9857f422df46d52f053c22d96c8c to your computer and use it in GitHub Desktop.
Save donpironet/f5ce9857f422df46d52f053c22d96c8c to your computer and use it in GitHub Desktop.
UINavigationController extension to fix back swipe when having custom back button
extension UINavigationController: UINavigationControllerDelegate, UIGestureRecognizerDelegate {
public override static func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
if self !== UINavigationController.self {
return
}
dispatch_once(&Static.token) {
// Swizzle viewDidLoad
self.swizzleViewDidLoad()
// Swizzle pushViewController
self.swizzlePushController()
}
}
// MARK: - Helpers
static func swizzleViewDidLoad() {
let originalViewDidLoadSelector = #selector(UINavigationController.viewDidLoad)
let swizzledViewDidLoadSelector = #selector(UINavigationController.newViewDidLoad)
let originalViewDidLoadMethod = class_getInstanceMethod(self, originalViewDidLoadSelector)
let swizzledViewDidLoadMethod = class_getInstanceMethod(self, swizzledViewDidLoadSelector)
let didAddViewDidLoadMethod = class_addMethod(self, originalViewDidLoadSelector, method_getImplementation(swizzledViewDidLoadMethod), method_getTypeEncoding(swizzledViewDidLoadMethod))
if didAddViewDidLoadMethod {
class_replaceMethod(self, swizzledViewDidLoadSelector, method_getImplementation(originalViewDidLoadMethod), method_getTypeEncoding(swizzledViewDidLoadMethod))
} else {
method_exchangeImplementations(originalViewDidLoadMethod, swizzledViewDidLoadMethod);
}
}
static func swizzlePushController() {
let originalPushControllerSelector = #selector(UINavigationController.pushViewController(_:animated:))
let swizzledPushControllerSelector = #selector(UINavigationController.newPushViewController(_:animated:))
let originalPushControllerMethod = class_getInstanceMethod(self, originalPushControllerSelector)
let swizzledPushControllerMethod = class_getInstanceMethod(self, swizzledPushControllerSelector)
let didAddPushControllerMethod = class_addMethod(self, originalPushControllerSelector, method_getImplementation(swizzledPushControllerMethod), method_getTypeEncoding(swizzledPushControllerMethod))
if didAddPushControllerMethod {
class_replaceMethod(self, swizzledPushControllerSelector, method_getImplementation(originalPushControllerMethod), method_getTypeEncoding(swizzledPushControllerMethod))
} else {
method_exchangeImplementations(originalPushControllerMethod, swizzledPushControllerMethod);
}
}
// MARK: - Method Swizzling
func newViewDidLoad() {
self.newViewDidLoad()
self.interactivePopGestureRecognizer?.delegate = self
self.delegate = self
}
func newPushViewController(viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = false
self.newPushViewController(viewController, animated: animated)
}
// MARK: - UINavigationControllerDelegate
public func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment