从自定义可编辑 UITableViewCell 更新另一个字符串 - 在 swift 中通过引用传递?

Update another string from custom editable UITableViewCell - pass by reference in swift?

我从 UITableViewCell 创建了一个 class,它允许我编辑正确的详细信息文本。它使用 UITextField 作为 editableAccessoryView。下面的代码。

问题是我需要根据更改更新字符串。 IE。编辑完成后,字符串将更新为 textField.text 字符串。

在另一种语言中,我可能在 UITableViewCell subclass 中有一个字符串指针,我会用我想更改的字符串的指针更新它。但是,尽管我可以使用 inout 将指针传递给函数,但我无法弄清楚如何存储该指针。

有什么想法吗?

import UIKit

class EditableRightDetailTableViewCell: UITableViewCell, UITextFieldDelegate {

    enum TextFieldType {
        case Text
        case Numeric
    }

    var type = TextFieldType.Text

    let textField = UITextField(frame: CGRectMake(150, 7, 200, 30))

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code

        textField.borderStyle = UITextBorderStyle.RoundedRect
        textField.textAlignment = NSTextAlignment.Right
        textField.clearButtonMode = UITextFieldViewMode.Always
        textField.delegate = self
        self.editingAccessoryView = textField
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    override func setEditing(editing: Bool, animated: Bool) {

        if !self.editing && editing == true {
            self.detailTextLabel?.hidden = true
            textField.text = self.detailTextLabel?.text
        }
        else if self.editing && editing == false {
            self.detailTextLabel?.hidden = false
            self.detailTextLabel?.text = textField.text
        }
        super.setEditing(editing, animated: animated)
    }

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

        if type == TextFieldType.Numeric {
            // We ignore any change that doesn't add characters to the text field.
            // These changes are things like character deletions and cuts, as well
            // as moving the insertion point.
            //
            // We still return true to allow the change to take place.
            if count(string) == 0 {
                return true
            }

            // Check to see if the text field's contents still fit the constraints
            // with the new content added to it.
            // If the contents still fit the constraints, allow the change
            // by returning true; otherwise disallow the change by returning false.
            let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)

            return prospectiveText.isNumeric() && count(prospectiveText) <= 11
        }
        return true
    }

}

不好的做法

您真的不想在 UITableViewCell 中保留指向对象的指针。首先,它们一般都被OS缓存起来,按需加载,总之,你不要企图拥有它们,当然要在里面保留指针。

良好做法

如果您的数据发生变化,请告诉 UITableView 重绘该单元格。您甚至可以重新绘制一个新的、不同的 UITableViewCell。 (您甚至可以使用通知,进一步将您的视图与模型分离

Swift

self.tableView.beginUpdates()
let indexPath = NSIndexPath(forRow: row, inSection: section)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.tableView.endUpdates()

Obj-C

[self.tableView beginUpdates];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:section];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];

他是我的实现如果有人感兴趣的话:

editable UITextViewCell。它应该在 IB 中设置为 Right Detail。当 table 视图设置为编辑时,将出现 UITextField。

import UIKit

class EditableRightDetailTableViewCell: UITableViewCell {

    let textField = UITextField(frame: CGRectMake(150, 7, 200, 30))

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code

        textField.borderStyle = UITextBorderStyle.RoundedRect
        textField.textAlignment = NSTextAlignment.Right
        textField.clearButtonMode = UITextFieldViewMode.Always
        self.editingAccessoryView = textField
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func initWithValues(label: String, detail: String) {
        self.textLabel!.text = label
        self.detailTextLabel?.text = detail
        textField.text = detail
    }

    override func setEditing(editing: Bool, animated: Bool) {

        if !self.editing && editing == true {
            self.detailTextLabel?.hidden = true
            textField.text = self.detailTextLabel?.text
        }
        else if self.editing && editing == false {
            self.detailTextLabel?.hidden = false
            self.detailTextLabel?.text = textField.text
            textField.endEditing(true)
        }
        super.setEditing(editing, animated: false)
    }
}

这是代表。请注意值已更改的变量。当值被更新时,它可以被分配给 运行 的闭包

import UIKit

class StringFieldDelegate: NSObject, UITextFieldDelegate {

    var value: String

    var valueChanged: Optional<() -> ()> = nil
    func invokeValueChanged() {
        self.valueChanged?()
    }

    init(value: String) {
        self.value = value
    }

    func textFieldDidEndEditing(textField: UITextField) {
        value = textField.text
        invokeValueChanged()
    }

    func textFieldShouldReturn(textField: UITextField) -> Bool {
        value = textField.text
        invokeValueChanged()
        return true
    }
}

然后在ViewController中我们创建像

这样的变量
var nameField: StringFieldDelegate!

并在 viewDidLoad

中初始化它们

在cell加载部分我们可以设置cell的delegate

cell.textField.delegate = nameField

现在,只要单元格完成编辑或按下 return,nameField 就会更新。 (对于即时更新,您必须实施 shouldChangeCharactersInRange 并更新值并在其中触发 invokeValueChanged

您还可以为值更改时分配一个闭包,例如

nameField.valueChanged = { println(nameField.value) }

委托可用于任何 UITextField。如果您实施 shouldChangeCharactersInRange,您可以执行以下操作:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

        if count(string) == 0 {
            return true
        }
        let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)

        return prospectiveText.isNumeric()
    }

这将使文本字段仅接受数字字符,使用扩展名

extension String {

    // Returns true if the string represents a proper numeric value.
    // This method uses the device's current locale setting to determine
    // which decimal separator it will accept.
    func isNumeric() -> Bool
    {
        let scanner = NSScanner(string: self)

        // A newly-created scanner has no locale by default.
        // We'll set our scanner's locale to the user's locale
        // so that it recognizes the decimal separator that
        // the user expects (for example, in North America,
        // "." is the decimal separator, while in many parts
        // of Europe, "," is used).
        scanner.locale = NSLocale.currentLocale()

        return scanner.scanDecimal(nil) && scanner.atEnd
    }

}