从 UIBarButtonItem 触发 textFieldShouldReturn

Posted

技术标签:

【中文标题】从 UIBarButtonItem 触发 textFieldShouldReturn【英文标题】:Trigger textFieldShouldReturn from UIBarButtonItem 【发布时间】:2017-11-02 03:02:30 【问题描述】:

我正在尝试添加一个触发我的textFieldShouldReturnUIBarButtonItem,但我收到此错误:

“#selector”的参数不引用“@objc”方法、属性或初始化程序

UIBarButtonItem

func addToolBar(textField: UITextField) 
    let toolBar = UIToolbar()
    toolBar.barStyle = .default
    let doneButton = UIBarButtonItem(
            title: "Done",
            style: .done,
            target: self,
            action: #selector(textFieldShouldReturn(textField))) //** ERROR **
    toolBar.isUserInteractionEnabled = true
    toolBar.sizeToFit()
    textField.inputAccessoryView = toolBar

textFieldShouldReturn:

@objc func textFieldShouldReturn(_ textField: UITextField) 
  print("hi there!")

错误提示我应该将objc 添加到我的textFieldShouldReturn,但我已经有了。我也已经尝试过以下方法:

Argument of '#selector' does not refer to an '@objc' method, property, or initializer Argument of '#selector' does not refer to an '@objc' method Argument of '#selector' does not refer to an initializer or method How to set the action for a UIBarButtonItem in Swift

有谁知道我如何设置我的UIBarButtonItem 来触发我的textFieldShouldReturn

【问题讨论】:

【参考方案1】:

这里有几个问题。

    textFieldShouldReturn 方法是UITextFieldDelegate 的委托方法。它只能由UITextField 调用。它有一个参数 - 文本字段。 UIBarButtonItem 目标/选择器必须是特定于处理按下按钮的方法。选择器需要具有两个可能的签名之一。这可以是没有参数的方法,也可以是带有一个参数的方法,即触发事件的UIBarButtonItem。 您正在尝试调用不匹配的UITextFieldDelegate 方法作为UIBarButtonItem 的选择器。那根本行不通。

如果您希望文本字段委托和按钮选择器都执行相同的操作,则让两个相应的方法中的每一个都调用第三种常用方法。

func textFieldShouldReturn(_ textField: UITextField) 
    processReturn()


@objc func barButtonAction(_ button: UIBarButtonItem) 
    processReturn()


func processReturn() 
    // Do whatever is needed

并设置栏按钮项:

let doneButton = UIBarButtonItem(
        title: "Done",
        style: .done,
        target: self,
        action: #selector(barButtonAction)

如果您的 processReturn 方法需要对文本字段的引用,请添加该参数。诀窍是从barButtonAction 方法获取对文本字段的引用。它不能作为参数传递给该方法,因此您需要有一个引用文本字段的属性。

【讨论】:

谢谢@rmaddy!这对我有用,我也能够获得对 textField 的引用。【参考方案2】:

在这里,您可以从按钮 Action 调用 textFieldSholdReturn 方法:

var textField : UITextField!



 override func viewDidLoad() 
        super.viewDidLoad()

        //Fixed space
        let fixed = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: self, action: nil)
        fixed.width = 10

        //Text
        let text = UIBarButtonItem(title: "My Title", style: UIBarButtonItemStyle.plain, target: self, action: nil)
        text.setTitleTextAttributes([
            NSAttributedStringKey.font : UIFont.systemFont(ofSize: 23.0),
            NSAttributedStringKey.foregroundColor : UIColor.white], for: UIControlState.normal)

        //TextField
        textField = UITextField(frame: CGRect(x: 0, y: 0, width: 150, height: 30))
        textField.delegate = self
        textField.textColor = UIColor.blue
        let border = CALayer()
        let width : CGFloat = 2.0
        border.borderColor = UIColor.white.cgColor
        border.frame = CGRect(x: 0, y: textField.frame.size.height-width, width: textField.frame.size.width, height: textField.frame.size.height)
        border.borderWidth = width
        textField.layer.addSublayer(border)
        textField.layer.masksToBounds = true
        let textFieldButton = UIBarButtonItem(customView: textField)

        //Search Button
        let search = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.search, target: self, action: #selector(ViewController.callExplictly(sender:)))

        //Flexible Space
        let flexible = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil)

        //Toolbar
        let toolbar = UIToolbar(frame: CGRect(x: 0, y: 20 , width: view.frame.width, height: 50))
        toolbar.sizeToFit()
        toolbar.barTintColor = UIColor.orange
        toolbar.isTranslucent = false
        toolbar.tintColor = UIColor.white
        toolbar.items = [fixed, text, fixed, textFieldButton, flexible, search]
        view.addSubview(toolbar)
    

你需要使用一个方法作为选择器,而不是直接调用textfield的Delgate方法

-- 将选择器添加到 UIBarButton :

 //Search Button
 let search = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.search, target: self, action: #selector(ViewController.callExplictly(sender:)))

这里需要Method来调用委托方法

@objc func callExplictly(sender: UIBarButtonItem)
        print("its called")
        if let textField = textField, let textFieldDelegate = textField.delegate 
            if textFieldDelegate.textFieldShouldReturn!(textField) 
                textField.endEditing(true)
            
        
 //here let textField --- Here I am just using. reference to TextField used  = textField --- this is textField declared and being used in Bar 
 //I am calling textField.endEditing(true) to dismiss opened Keyboard as Done button refer that My action required on TF is completed now I can Dismiss keyboard too.
 // As here textFieldDelegate.textFieldShouldReturn!  -- (!) this symbolises as textFieldShouldReturn is a delegate method of TextField and I am accessing that using a reference which is not of textField Type So I am using ! as optional so, it dont jump over the function and call it

    

 func textFieldDidBeginEditing(_ textField: UITextField) 

        view.backgroundColor = UIColor.yellow

    

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
        view.backgroundColor = UIColor.cyan

        //Hide the keyboard
        textField.resignFirstResponder()
    

这里是被调用的委托方法

 func textFieldShouldReturn(_ textField: UITextField) -> Bool 

        view.backgroundColor = UIColor.white
        print("Called")

        //Hide the keyboard
        textField.resignFirstResponder()
        return true
    

还请检查我的代码文件以供参考:

Link : https://drive.google.com/open?id=0Bz8kF1Gedr7fcTdEX29WX1JvYlU

【讨论】:

1. textField 来自 callExplicitly 方法内部的什么地方? 2、为什么调用textFieldDelegate.textFieldShouldReturn!(textField)时会有!? 3. 为什么打电话给endEditing?您已经辞去了第一响应者的职务。 你检查过我在这里分享的代码文件吗? if let textField // 我正在创建一个引用 = textField // 这个 TF 在 Bar 中使用 请在此处查看我更新的答案 我在此处发布了更多 cmets @iosGeek 这对我不起作用,但一如既往,感谢您的回复。附带说明一下,似乎链接到个人 google 驱动器文件是一种不好的做法,因为它很容易将 SO 用户引导到潜在的恶意文件。只是值得深思

以上是关于从 UIBarButtonItem 触发 textFieldShouldReturn的主要内容,如果未能解决你的问题,请参考以下文章

UIBarButtonItem 在显示两次后未触发选择器

动态创建的 UIBarButtonItem 不会在点击时触发

UIBarButtonItem 仅在按下足够长的时间时才会触发动作

使用 swift 访问 UIBarButtonItem textfield.text

UIBarButtonItem - 全宽没有灵活空间

没有为 UIBarButtonItem 调用 iOS 选择器