我正在尝试UITextFieldDelegate使用协议扩展在某些方法上添加默认行为,例如:
UITextFieldDelegate
extension ViewController: UITextFieldDelegate { // Works if I uncommented this so I know delegates are properly set // func textFieldShouldReturn(textField: UITextField) -> Bool { // textField.resignFirstResponder() // return true // } } extension UITextFieldDelegate { func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true } }
您可能会猜到,键盘永远不会消失。我真的看不出问题出在哪里。这是语言限制吗?有人已经成功做到了吗?
编辑:
正如@Logan所建议的,默认协议的方法实现不适用于标记为的协议@objc。但是,UITextFieldDelegate具有以下签名public protocol UITextFieldDelegate : NSObjectProtocol {...}
@objc
public protocol UITextFieldDelegate : NSObjectProtocol {...}
我已经测试了默认的实现NSObjectProtocol,它似乎运行良好:
NSObjectProtocol
protocol Toto: NSObjectProtocol { func randomInt() -> Int } extension Toto { func randomInt() -> Int { return 0 } } class Tata: NSObject, Toto {} let int = Tata().randomInt() // returns 0
我不能100%积极,但是我相信这是正在发生的事情:
无法从访问协议扩展ObjC。由于UITextFieldDelegate是ObjC协议,因此它依赖于ObjC调度。就编译器而言,默认实现中的方法即使存在也无法访问。
ObjC
为了明确起见,我们可以扩展这些协议(如果它确实是扩展名)并增加行为。此行为只能在Swift中访问,并且绝不会出现任何问题。
问题是默认实现无法ObjC访问。
这是自定义版本的快速示例:
@objc protocol Test : class { func someFunc() -> String } extension Test { func someFunc() -> String { return "" } } // Fails here 'candidate is not @objc but protocol requires it` class Hi : NSObject, Test { }
Xcode建议附加,@objc但是它将一遍又一遍地建议,直到您得到@objc @objc @objc Hi : ...
@objc @objc @objc Hi : ...
根据下面的对话,我认为这很有效。我还不能完全解释原因:
@objc public protocol Toto: UITextFieldDelegate { optional func randomInt() -> Int } extension Toto { func randomInt() -> Int { return 0 } func textFieldShouldReturn(textField: UITextField) -> Bool { return false } } class Tata: NSObject, Toto { }
好的,我意识到我正在考虑一个不同的问题,尽管此问题可以编译,但无法正常工作,而该问题是动态调度。如果尝试使用w @objc或追加方法dynamic,则编译器会警告您除类之外,不能以这种方式分派。由于协议异常不符合此要求,因此ObjC调度消息发送时,无法在扩展中找到实现。
dynamic
由于Swift一直在不断更新,因此适用此答案的时间是:
Swift 2.0 Xcode 7 GM