【问题标题】:Add Target to UITextField within a UITableview (Swift)在 UITableview (Swift) 中将 Target 添加到 UITextField
【发布时间】:2019-08-01 03:05:58
【问题描述】:

我想检查用户何时开始编辑文本字段。关于如何做到这一点here 有一个非常明确的答案。

但是,在我的情况下,我的 textField 位于设置为自己的类的 UITableview 中。我已经尝试了很多不同的方法来让它工作,但我不断收到崩溃“libc++abi.dylib:以 NSException 类型的未捕获异常终止”我在 textFieldDidChange 函数中设置了一个中断,它永远不会被调用问题似乎在于我如何从目标调用该函数。

class TextFieldCell: UITableViewCell {

    lazy var textField: UITextField = {
        let tf = UITextField()
        tf.translatesAutoresizingMaskIntoConstraints = false
        tf.textAlignment = .center
        tf.textColor = .black
        tf.font = UIFont.systemFont(ofSize: 17)
        tf.clearButtonMode = .whileEditing
        return tf
    }()

    // For simplicity, the rest of the Cell setup not shown.
    // Adds target in AirInput VC to fire method when editing happens

    textField.addTarget(self, action: #selector(AirInputViewController.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)

}


class AirInputViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {

    @objc func textFieldDidChange(_ textField: UITextField) {

    }

}

我还为目标尝试了以下操作,但它也崩溃了。

textField.addTarget(AirInputViewController.self, action: #selector(AirInputViewController.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)

感觉好像我错过了一些简单的东西,但我不知道那个简单的修复是什么。或者也许我应该在 AirInputViewContoller 中添加目标?如果是这样,我将如何访问文本字段所在的 UITableViewCells?谢谢!

【问题讨论】:

  • 通常在“以 NSException 类型的未捕获异常终止”之前有一个指针指向导致异常的原因。你介意发布整个崩溃吗?
  • 你是这个意思吗? “libc++abi.dylib:以 NSException 类型的未捕获异常终止”
  • 不,通常输出会更长。我有预感会发生什么。发布了答案。如果不是这样,我可以删除它。

标签: ios swift uitableview uitextfield


【解决方案1】:

您的崩溃可能是由于您这样做:

textField.addTarget(self, action: #selector(AirInputViewController.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)

这里selfTextFieldCell,所以我认为它会尝试检查AirInputViewController 是否在TextFieldCell 中,但事实并非如此。

我愿意:

class TextFieldCell: UITableViewCell {

    weak var delegate: TextFieldCellDelegate?

    lazy var textField: UITextField = {
        // same you have
    }()

    textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: UIControl.Event.editingChanged)

    @objc func textFieldDidChange(_ textField: UITextField) {
        delegate?.textFieldDidChange(textField)
    }

创建一个精美的委托:

protocol TextFieldCellDelegate: class {
     func textFieldDidChange(_ textField: UITextField)
}

class AirInputViewController: TextFieldCellDelegate {

    func textFieldDidChange(_ textField: UITextField) {
        // textField just changed!
    }

    // IMPORTANT! Set the delegate for the cell!

    func tableView(...cellForRow...) {
        let cell = ... as! TextFieldCell
        cell.delegate = self
        ...
        return cell
    }
}

希望对您有所帮助。

【讨论】:

  • 我想我知道你要去哪里,但不能让它发挥作用。协议的目的是什么?实现时出现错误“objc 只能与类成员、@objc 协议和类的具体扩展一起使用”。
  • 对不起,协议及其textFieldDidChange 不应该是@objc。该协议的目的是创建一个委托。单元格内的事件然后在单元格内处理,并且使用delegate 通知控制器控制器需要知道的事件,仅此而已。基本上,视图的事件观察者应该在该视图内,而不是在不同的类中。
  • 感谢您的帮助。现在没有@objc,它会给出错误“协议方法不能有主体”。
  • 成功了!非常感谢您与我一起工作并教我一些新东西。现在我只需要盯着它看一会儿,以更好地了解正在发生的事情。 :)
  • 委托模式在 Swift 中非常有用和传播,所以我建议你熟悉它。这里有一些例子和解释:stackoverflow.com/questions/7168714/…。这里的协议继承自class,因此变量可以是weak,这样可以避免保留周期,因为控制器具有视图并且视图将控制器的引用作为委托。所以通过弱化委托,视图没有对控制器的强引用,也没有循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 2015-05-23
  • 2016-06-19
  • 2017-06-15
  • 1970-01-01
相关资源
最近更新 更多