3

I'm trying to use the rightView property of the UITextField class to provide a suffix to a text field. It all seems to work correctly, until I stop editing the text field, at which point the label is moved outside of the UITextField. The code used is:

class TextFieldWithSuffix: UITextField {
    var suffix: String? {
        didSet {
            let value = self.suffix ?? ""
            let label = UILabel(frame: CGRectZero)
            label.font = self.font
            label.text = value

            self.rightView = label
            self.rightViewMode = .Always
        }
    }

    override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
        var rightViewRect = super.rightViewRectForBounds(bounds)
        if let suffix = self.suffix {
            let suffixSize = NSString(string: suffix).sizeWithAttributes([NSFontAttributeName: self.font])
            rightViewRect.size = suffixSize
        }
        return rightViewRect
    }
}

When the view is first loaded the view looks like below:

enter image description here

However, when the text field has been edited and then the keyboard dismissed, it looked like below:

enter image description here

This has been tested on iOS 7 and 8 and both seem to be doing the same.

Joseph Duffy
  • 4,566
  • 9
  • 38
  • 68

1 Answers1

2

Turns out the issue was setting the rightView property again, which was happening when the editing finished. I found the following version fixed the issue:

class TextFieldWithSuffix: UITextField {
    var suffix: String? {
        didSet {
            let value = self.suffix ?? ""

            let suffixLabel = UILabel(frame: CGRectZero)
            suffixLabel.font = self.font
            suffixLabel.updateFontStyle()
            suffixLabel.text = value

            self.rightView = nil
            self.rightView = suffixLabel
            self.rightViewMode = .Always

            self.setNeedsLayout()
            self.layoutIfNeeded()
        }
    }

    override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
        var rightViewRect = super.rightViewRectForBounds(bounds)
        if let suffix = self.suffix {
            let suffixSize = NSString(string: suffix).sizeWithAttributes([NSFontAttributeName: self.font])
            rightViewRect.size = suffixSize
        }
        return rightViewRect
    }
}

Hopefully this'll help someone. If you're doing this a lot you should just update the value of the label and call the setNeedsLayout() and layoutIfNeeded(), but this works so I'm just leaving it as-is.

Joseph Duffy
  • 4,566
  • 9
  • 38
  • 68