Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save EfraimB/df9916d781128ead73fa025cda7a9bc3 to your computer and use it in GitHub Desktop.
Save EfraimB/df9916d781128ead73fa025cda7a9bc3 to your computer and use it in GitHub Desktop.
public extension UIView {
private struct ExtendedTouchAssociatedKey {
static var outsideOfBounds = "viewExtensionAllowTouchesOutsideOfBounds"
}
var allowTouchesOutsideOfBounds:Bool {
get {
return objc_getAssociatedObject(self, &ExtendedTouchAssociatedKey.outsideOfBounds) as? Bool ?? false
}
set {
UIView.swizzlePoinInsideIfNeeded()
objc_setAssociatedObject(self, &ExtendedTouchAssociatedKey.outsideOfBounds, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
func hasSubviewAllowingTouchesOutsideOfBounds(at point:CGPoint) -> Bool {
if allowTouchesOutsideOfBounds && self.bounds.contains(point) {
return true
}
return subviews.contains(where: { (subview) -> Bool in
let converted = self.convert(point, to: subview)
return subview.hasSubviewAllowingTouchesOutsideOfBounds(at: converted)
})
}
static private var swizzledMethods:Bool = false
@objc func _point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return _point(inside:point,with:event) || hasSubviewAllowingTouchesOutsideOfBounds(at: point)
}
static private func swizzlePoinInsideIfNeeded() {
if swizzledMethods {
return
}
swizzledMethods = true
let aClass: AnyClass! = UIView.self
let originalSelector = #selector(point(inside:with:))
let swizzledSelector = #selector(_point(inside:with:))
swizzle(forClass: aClass, originalSelector: originalSelector, swizzledSelector: swizzledSelector)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment