'textFieldDidBeginEditing' 几乎符合 Swift 中协议 'UITextFieldDelegate' 的可选要求 'textFieldDidBeginEditing'

'textFieldDidBeginEditing' nearly matches optional requirement 'textFieldDidBeginEditing' of protocol 'UITextFieldDelegate' in Swift

我正在开发一个应用程序,我在其中为应用程序的每个功能创建了模块。我必须从一个模块 UI 控制器切换到另一个模块 UI 控制器。

我在模块中有 UI控制器,我将该控制器标记为 Public 访问标识符,如下所示

public class InterAccountTransferViewController: UIViewController {
   override public func viewDidLoad() {
    ......
    ......
   }
}

以上 class 还在扩展中实现了 UITextField 委托。当我在 class 上方创建为开放访问时,我在 TextField 委托上收到如下警告

Instance method 'textFieldDidBeginEditing' nearly matches optional requirement 'textFieldDidBeginEditing' of protocol 'UITextFieldDelegate'

现在不调用文本字段委托。当我试图通过将代表设为私有来关闭警告时,他们仍然没有被调用。

请告诉我如何消除这些警告并同时致电代表。

任何想法或建议都会很棒。我正在使用 swift 4.2 开发 Xcode 10。如果我需要进一步解释我的问题,请告诉我。

将您的方法也标记为public

public func textFieldDidBeginEditing(_ textField: UITextField)

试试这个

class InterAccountTransferViewController: UIViewController,UITextFieldDelegate {
 override func viewDidLoad() {
    super.viewDidLoad()
    //Attach delegates 
    self.textfield.delegate = self
 }
   //TextField Delegate Method
   public func textFieldDidBeginEditing(_ textField: UITextField) {
   }
} 

对于 "Nearly matches",编译器会告诉您两件事:

  1. 不匹配:方法'textFieldDidBeginEditing(_:)'与委托方法'textFieldDidBeginEditing(_:)'不同。这本身对编译器来说不是问题,你只是有一个有名字的方法,它不知道这个名字,所以没关系。
  2. 非常像委托方法'textFieldDidBeginEditing(_:)'。所以编译器可以看到您可能打算将其作为一个委托方法,并且它告诉您,好吧,它不起作用。你写的不是委托方法。

编译器告诉你有问题,这很好。不太好,没有说明问题到底是什么。

问题是你的class比委托方法有更多的可见性。你的class是public,而你的委托方法只是 internal(因为 internal 是默认值,如果您的声明中没有访问说明符。)

修复方法是也为委托方法提供一个 public 访问说明符。

你必须改变

func textFieldDidBeginEditing(_ textField: UITextField) {
    // ...
}

public func textFieldDidBeginEditing(_ textField: UITextField) {
    // ...
}

这会让编译器知道该方法确实是一个委托方法。


奖励内容...

我是如何找到解决方案的? 我在 Xcode 中重现了这个问题。我单击了警告并阅读了 Fixup:"Make 'textFieldDidBeginEditing' non-public to silence this warning"。我点击了 "Fix",该行更改为 "private func textFieldDidBeginEditing(_ textField: UITextField)"。所以我想也许把它变成 public 而不是 private 会更有帮助。我试过,检查过,成功了。

为什么 Swift 会这样做? 我不确定,但我的猜测是:如果 class 是 public,但是协议方法是内部的,这意味着当你从模块的角度来看时,一个单独的视图控制器对象实现了协议。但由于协议实现是内部的,从外部模块的角度看,协议方法将不可用,例如来自 UIKit。但这在 Objective C 运行时是不可能的,即使可能也是不好的。默默地制作协议方法 public 或 semi-public 是可能的,但不是很干净:例如可以将 textFieldDidBeginEditing 设为内部,但是当您将对象转换为 UITextFieldDelegate 伪对象时,您可以突然调用该方法,这同样令人惊讶。

只需像这样在您的函数中添加 public 访问修饰符。

public func textFieldDidBeginEditing(_ textField: UITextField) {
     // do whatever you want
}