【问题标题】:'textFieldDidBeginEditing' nearly matches optional requirement 'textFieldDidBeginEditing' of protocol 'UITextFieldDelegate' in Swift'textFieldDidBeginEditing' 几乎匹配 Swift 中协议'UITextFieldDelegate' 的可选要求'textFieldDidBeginEditing'
【发布时间】:2019-06-02 01:49:36
【问题描述】:

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

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

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

上面的类还在扩展中实现了 UITextField 委托。当我将上面的类创建为开放访问时,我收到关于 TextField 代表的警告,如下所示

实例方法“textFieldDidBeginEditing”几乎匹配可选 要求协议的“textFieldDidBeginEditing” 'UITextFieldDelegate'

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

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

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

【问题讨论】:

  • 确保几点。 - 你有没有像 self.textfield.delegate = self. - public class InterAccountTransferViewController: UIViewController,UItextFieldDelegate { } , - 在上面的警告中,点击黄色条,它必须建议更新委托方法签名。
  • @Sakshi 我已经尝试过了,但没有成功。
  • @RobertDresler 我已经尝试过 at:objc 但没有效果。

标签: ios swift delegates compiler-warnings access-modifiers


【解决方案1】:

使用“几乎匹配”,编译器会告诉您两件事:

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

编译器很高兴它告诉您存在问题。不太好,它没有解释到底是什么问题。

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

解决方法是给委托方法一个public 访问说明符。

你必须改变

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

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

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


奖励内容...

我是如何找到解决方案的?我在 Xcode 中重现了这个问题。我单击了警告并阅读了 Fixup:“将 'textFieldDidBeginEditing' 设为非公开以使此警告静音”。我单击“修复”,该行更改为“private func textFieldDidBeginEditing(_ textField: UITextField)”。所以我想也许把它改成public 而不是private 会更有帮助。我试过了,检查了一下,它成功了。

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

【讨论】:

  • 很好的解释。可惜我在找到它之前尝试了 2 个小时来了解发生了什么。
  • 我不明白。为什么私人和公共都可以工作,而内部却不行?!
  • @Honey: private 并没有真正起作用。它只是编译。只有public 有效。由于 UITextFieldDelegate 协议是公开的,因此一致性也必须是公开的,这样每个可以看到一致性的人也可以调用该方法。如果您将其设为private,则它不再是一致性,它只是一个完全不相关的方法,与 UITextFieldDelegate 方法之一具有相同的名称。
  • 因此编译器的建议最终具有误导性。即你说'这不是很好,它不能解释问题到底是什么。应该更多的是“它的信息具有误导性,这不太好”
【解决方案2】:

试试这个

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

【讨论】:

    【解决方案3】:

    将您的方法也标记为public

    public func textFieldDidBeginEditing(_ textField: UITextField)
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2018-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-24
        相关资源
        最近更新 更多