繁体   English   中英

swift 2.0 - UITextFieldDelegate协议扩展无法正常工作

[英]swift 2.0 - UITextFieldDelegate protocol extension not working

我正在尝试使用协议扩展在某些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 {...}

我测试了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调度。 就编译器而言,即使它们确实存在,默认实现中的方法也是不可访问的。

为了澄清,我们可以扩展这些协议,如果它真正的扩展和添加行为。 此行为只能在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 {
}

好吧,我意识到我正在考虑一个不同的问题,虽然这个编译,它将无法工作,问题是动态调度。 如果您尝试使用@objcdynamic附加方法,编译器将警告您不能以这种方式调度,除了类。 由于协议异常不符合这一点,当ObjC调度消息send时,它无法在您的扩展中找到实现。

由于Swift不断更新,所以这个答案适用时:

Swift 2.0 Xcode 7 GM

这里讨论得很好,而且我现在正在怀疑这一点。 这里没有提到的另一件事 - 也许这可能是由于更广泛的obj-c无法访问Swift协议扩展实现的问题。

例如,以下代码:

class MyViewController: UIViewController, MyTextFieldDelegateProtocol {
    @IBOutlet weak var textField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self
    }
}
extension MyViewController: UITextFieldDelegate {
    func textFieldDidBeginEditing(textField: UITextField) {
        print("shouldChangeCharactersInRange called")
    }
}

将在Swift生成的扩展头中生成以下内容:

@interface MyViewController (SWIFT_EXTENSION(MyApp)) <UITextFieldDelegate>
- (void)textFieldDidBeginEditing:(UITextField * __nonnull)textField;
@end

但是,使用协议扩展如下(类似于您的帖子):

class MyViewController: UIViewController, MyTextFieldDelegateProtocol {
    // ...
}

@objc protocol MyTextFieldDelegateProtocol: UITextFieldDelegate {}
extension MyTextFieldDelegateProtocol {
    func textFieldDidBeginEditing(textField: UITextField) {
        print("shouldChangeCharactersInRange called")
    }
}

在协议的Swift头中生成以下内容:

SWIFT_PROTOCOL("_TtP8MyApp27MyTextFieldDelegateProtocol_")
@protocol MyTextFieldDelegateProtocol <UITextFieldDelegate>
@end

实现根本不可见,因此似乎暗示obj-c不支持协议扩展实现。 我也发现有人在这里问了这个问题(虽然还没有答案): Swift方法可以定义在Objective-c中访问的协议的扩展

不幸的是,我还没有找到任何有关此限制的官方苹果文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM