poetmountain / PMValidation

A modular, extendable text validation library for iOS.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Comparing text entered from keyboard and programmatically works different.

matrosovDev opened this issue · comments

If I enter text from keyboard it works good, but if I set text programmatically, by some reasone it does not work:

I have source code

private func validate() -> (state: Bool, errorMessage: String?)
{
var validState: (state: Bool, errorMessage: String?) = (true, nil)

for unit in validationUnits {
  unit.validateText(textField.text)
  if !unit.isValid {
    validState.errorMessage = errorMessages[unit.identifier]
    validState.state = false
    break
  }
}
return validState

}

unit.validateText(textField.text) works ok if we entered text from keyboard, but if we set textField.text programmatically it won't work =(

PMValidationUITextCompareType uses the system UITextFieldTextDidChangeNotification notification to detect changes to a UITextField via the keyboard. This notification is not triggered by setting the text directly in code. PMValidationUITextCompareType is really just meant for cases where only the user is updating text via the keyboard.

To update the validation in both cases, you'll have to trigger the validation check manually when you set update the UITextField via code. To do that, you'll need to manually set the PMValidationUITextCompareType's comparisonString property before you call validateText on the PMValidationUnit. Example:

PMValidationUITextCompareType *validator = (PMValidationUITextCompareType *)[unit validationTypeForIdentifier:@"email"]; // use whatever label you used when creating the type
validator.comparisonString = self.emailText.text;
unit.validateText(textField.text)

You have to set it manually because PMValidationUITextCompareType will normally only get its string updates from the UITextField.

Hope that helps!

Thanks for detailed answer. Unfortunately forced set does not work for me. Maybe I did something wrong:

for unit in validationUnits {

 ```

if let validator = unit.validationTypeForIdentifier(validationIdentifier) as? PMValidationUITextCompareType {
validator.comparisonString = textField.text
}

  unit.validateText(textField.text)
  if !unit.isValid {
    validState.errorMessage = errorMessages[unit.identifier]
    validState.state = false
    break
  }
}

it never gets  validator.comparisonString = textField.text string 

I registered it as

let emailValidationIdentifier = PMValidationEmailType.type()
validationManager.registerInputView(emailInput, validator: PMValidationEmailType.validator(), identifier:emailValidationIdentifier)

here we have a code:

- (PMValidationType *)validationTypeForIdentifier:(NSString *)theIdentifier {

    PMValidationType *validation_type = nil;

    for (PMValidationType *this_type in self.registeredValidationTypes) {
        if ([this_type.identifier isEqualToString:theIdentifier]) {
            validation_type = this_type;
            break;
        }
    }

    return validation_type;

}

I've checked self.registeredValidationTypes and we have type but this_type.identifier = ""

ok got it's different identifier. but in any case I have PMValidationType not PMValidationUITextCompareType

I meant that I don't know how to make it work:
validator.comparisonString, that type does not have this property

The validationTypeForIdentifier method returns the base PMValidationType type, so you have to explicitly cast it to the type you need. Once you cast it to PMValidationUITextCompareType you'll have access to the comparisonString property. But make sure you have the right identifier though (or just save a reference to the unit in your class) -- your code has a PMValidationEmailType, which doesn't have a comparisonString property.

By the way, it's not a good idea to check "unit.isValid" right after you call validateText. The validations are done asynchronously, so you should listen for PMValidationUnitUpdateNotification notifications (or PMValidationStatusNotification if you're using a PMValidationManager) to get validation updates. Calling 'validateText' on a unit should trigger those.

your code has a PMValidationEmailType, which doesn't have a comparisonString property.

  • yea I need to check email =) what should I do?

and also can I don it synchronously? because I log in and need to be sure that I sync this operation

So few problem here I faced:

  1. Validation not textField, but text especially email and password. So I am not sure how can use PMValidationUITextCompareType for validation email address as I use PMValidationEmailType. And as I understood I need to have PMValidationUITextCompareType because we need to set comprisingString but it's not available for PMValidationEmailType.
  2. Async validation. So for signing in I guess it's ok to have sync validation. But I guess there is not function like that?

Thanks for help!

You mentioned keyboard input worked but manually setting text didn't; that's why I thought you were using PMValidationUITextCompareType. Your first code sample you posted has a "textField.text" in it.

In any case, if you're just using PMValidationEmailType, then calling validateText on the PMValidationUnit will tell the email type to validate the text you passed in, so I'm not sure why you're saying it doesn't work? If you want to get low-level, you can even just call isTextValid() on the email validator directly.

getting isTextValid seems works fine! thanks for help