Eureka: Added support for maximum text field lengths

Created on 3 Aug 2016  路  6Comments  路  Source: xmartlabs/Eureka

It would be mighty handy to be able to put a hard limit on the amount of characters that can be input on both TextRow and TextAreaRow. For example:

TextAreaRow("comments") {
    // ...
    $0.maxLegth = 60
}

In the meantime, is there a standard-ish hack to add support for this?

Thanks!

FieldRow enhancement

Most helpful comment

Alright, I hacked away at it a bit and came up with this Gist.

Here's how to use it:

  1. Make your view controller extends MyFormViewController.
  2. Specify a maxLength property on any TextRow or TextAreaRow.
  3. Ensure that the row has a tag specified.

Definitely not ideal, but it allows for the syntax and behavior I laid out in the original post. If anyone notices problems or has any improvement suggestions, let me know.

All 6 comments

Alright, I hacked away at it a bit and came up with this Gist.

Here's how to use it:

  1. Make your view controller extends MyFormViewController.
  2. Specify a maxLength property on any TextRow or TextAreaRow.
  3. Ensure that the row has a tag specified.

Definitely not ideal, but it allows for the syntax and behavior I laid out in the original post. If anyone notices problems or has any improvement suggestions, let me know.

Thanks for sharing it!!

Hi, no plan to support this? For ex, using rules like RuleMaxLength to enforce the maximum input length.

The complete example is
TextAreaRow("comments") {
// ...
$0.tag = "comments"
$0.maxLength = 60
}

I get an error when putting the maxLength before the tag.

One small issue is that when the text area is having more than the maxLength, using backspace won't be able to remove the text there.

I had the similar requirement also I have want to restrict the character set of the row. Instead of extending the Row I have defined an other protocol:

public protocol InputFilter {
    var allowedCharacterSet: CharacterSet? { get set }
    var maxCharCount: Int { get }
}

and than I have defined my own cell and row:

open class GSSTextCell: _FieldCell<String>, CellType, InputFilter {

    public var allowedCharacterSet: CharacterSet?
    public var maxCharCount: Int = 1000

    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    open override func setup() {
        super.setup()
        textField.autocorrectionType = .no
        textField.autocapitalizationType = .allCharacters
        textField.keyboardType = .default
    }

    open override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let cs = CharacterSet(charactersIn: string)
        // checking empty string for backspace key
        return string == "" || (textField.text?.count)! < maxCharCount && allowedCharacterSet?.isSuperset(of: cs) == true
    }
}
open class _GSSTextRow: FieldRow<GSSTextCell> {
    public required init(tag: String?) {
        super.init(tag: tag)
    }
}



md5-11ace0830dbb0687c53f1ee0fe6ffb1b



public final class CharacterCountAndCharacterSetRestrictedRow: _GSSTextRow, RowType {
    public required init(tag: String?) {
        super.init(tag: tag)
        cellSetup { cell, row in
            cell.allowedCharacterSet = CharacterSet(charactersIn: "PACFGINSMTVO")
            cell.maxCharCount = 1
        }
    }
}

Checking empty string is required to able to use backspace key. This way I do not have to override textField functions on controller level.

You can achieve functionality like this using custom Formatter,

This should get you started

class StringMaxLengthFormatter: Formatter {

let maxLength: Int
/* ... */  
    override func string(for obj: Any?) -> String? {
        if let string = obj as? String {
            return String(string.prefix(maxLength))
        }
        return nil
    }

    override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {

        if let obj = obj {
            obj.pointee = self.string(for: string) as AnyObject?
        }

        return true
    }
}

Usage:

<<< TextRow {
            $0.useFormatterDuringInput = true
            $0.formatter = StringMaxLengthFormatter(maxLength: 10)
}
Was this page helpful?
0 / 5 - 0 ratings