ios type swift 2.0-расширение протокола UITextFieldDelegate не работает




uitextfield returnkeytype (2)

Хорошее обсуждение здесь, и именно то, что я подозреваю в этом пункте также. Еще одна вещь, не упомянутая здесь - возможно, это может быть связано с более широкой проблемой того, что 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

К сожалению, я еще не нашел официальных документов Apple об этом ограничении.

Я пытаюсь добавить поведение по умолчанию для некоторых 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 @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 отправляет отправленное сообщение, он не может найти реализацию в вашем расширении.

Поскольку Swift постоянно обновляется, вот когда этот ответ был применим:

Swift 2.0 Xcode 7 GM





uitextfielddelegate