Here is a small weak solution that includes related objects and the swizzling method.
, UITextField , , . , , - - canBecomeFirstResponder, . , canBecomeFirstResponder defaultValue - , .
UITextField, swizzling :
public extension UITextField {
private struct AssociatedKeys {
static var HandlerKey = "xxx_canBecomeFirstResponder"
}
public typealias CanBecomeFirstResponderHandler = (fromUserInteraction: Bool,
defaultValue: Bool) -> Bool
private class AnyValueWrapper {
var value: Any?
}
public var canBecomeFirstResponderHandler: CanBecomeFirstResponderHandler? {
get {
let wrapper = objc_getAssociatedObject(self,
&AssociatedKeys.HandlerKey)
return (wrapper as? AnyValueWrapper)?.value
as? CanBecomeFirstResponderHandler
}
set {
if let newValue = newValue {
let wrapper = AnyValueWrapper()
wrapper.value = newValue
objc_setAssociatedObject(
self,
&AssociatedKeys.HandlerKey,
wrapper,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
return
}
objc_setAssociatedObject(
self,
&AssociatedKeys.HandlerKey,
nil,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
if self !== UITextField.self {
return
}
dispatch_once(&Static.token) {
let originalSelector =
#selector(UITextField.canBecomeFirstResponder)
let swizzledSelector =
#selector(UITextField.xxx_canBecomeFirstResponder)
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 xxx_canBecomeFirstResponder() -> Bool {
let defaultValue = xxx_canBecomeFirstResponder()
if let canBecomeFirstResponder = canBecomeFirstResponderHandler {
var isFromUserInteraction = false
if let gestureRecognizers = gestureRecognizers {
for gestureRecognizer in gestureRecognizers {
if (gestureRecognizer.state == .Began ||
gestureRecognizer.state == .Changed ||
gestureRecognizer.state == .Ended)
{
isFromUserInteraction = true
break
}
}
}
return canBecomeFirstResponder(
fromUserInteraction: isFromUserInteraction,
defaultValue: defaultValue
)
}
return defaultValue
}
}
:
alertController.addTextFieldWithConfigurationHandler { textfield in
textfield.text = "Text"
textfield.canBecomeFirstResponderHandler = {
fromUserInteraction, defaultValue in
return fromUserInteraction
}
}
, :
:
alertController.view.endEditing(true)
.