Сохранение ссылки на текстовое поле UITextField

Проблема:

Я пытаюсь создать собственный класс UITextField «UIValidatedTextField», который позволяет установить определенные правила относительно того, является ли ввод действительным. Например, вы можете установить параметр регулярного выражения, чтобы гарантировать, что ввод имеет определенный формат, то есть пароль, адрес электронной почты и т. д....

Другая возможность этого заключается в том, чтобы указать и установить параметр, который ссылается на другой UITextField и гарантирует, что ввод соответствует вводу из этого другого UITextField.

Проблема, с которой я здесь сталкиваюсь, заключается в том, что я устанавливаю эту ссылку на другой UITextField. Однако, когда я получаю доступ к его «текстовому» полю, я обнаруживаю, что в текстовом поле ничего нет, даже когда я что-то в него ввожу.

Я предоставил соответствующий код ниже:

#import "UIRegisterViewController.h"
#import "UIRegisterViewCell.h"
#import "UIValidatedTextField.h"
#import "NSConstants.h"

@interface UIRegisterViewController ()


@end

@implementation UIRegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _tableView.delegate = self;
    _tableView.dataSource = self;
    _tableItems = @[@"name", @"email", @"netId", @"username", @"password", @"confirmPassword"];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [_tableItems count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *cellIdentifier = [_tableItems objectAtIndex:indexPath.row];
    UIRegisterViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];


    if ([cellIdentifier isEqualToString:@"email"]) {
        [cell.textField setRegex:VALID_DUKE_EMAIL_REGEX];

    } else if ([cellIdentifier isEqualToString:@"netId"]) {
        //Validation?

    } else if ([cellIdentifier isEqualToString:@"username"]) {
        //Validation?

    //THIS IS THE CELL THAT I WANT TO COMPARE INPUT TO
    } else if ([cellIdentifier isEqualToString:@"password"]) {
        [cell.textField setRegex:VALID_PASSWORD_REGEX];

    //SETTING THE TEXT FIELD IN QUESTION HERE...
    } else if ([cellIdentifier isEqualToString:@"confirmPassword"]) {
        [cell.textField setRegex:VALID_PASSWORD_REGEX];
        NSIndexPath *index = [NSIndexPath indexPathForRow:4 inSection:0];
        UIRegisterViewCell *confirm =(UIRegisterViewCell *)[self tableView:_tableView cellForRowAtIndexPath:index];
        [cell.textField setConfirm:confirm.textField];
    }

    cell.textField.delegate = self;
    return cell;
}

#pragma mark - Text Field Delegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}


@end

Обратите внимание, что textFields являются UIValidatedTextFields — настраиваемым классом, представленным ниже:

    #import "UIValidatedTextField.h"
#import "NSArgumentValidator.h"

@implementation UIValidatedTextField

- (id) initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self initialize];
    }
    return self;
}

- (id)initialize {
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldDidChange:)
                name:UITextFieldTextDidChangeNotification object:self];
        [self validate]; //Validate in case editing began before observer was set.
    }
    return self;
}

- (void) setOptional:(BOOL)isOptional {
    _isOptional = isOptional;
}

- (BOOL) isOptional {
    return _isOptional;
}

- (void) setRegex:(NSString *)regex {
    _regex = regex;
}

//SET THE TEXT FIELD TO COMPARE INPUT AGAINST HERE.
- (void) setConfirm:(UITextField *)confirm {
    _confirm = confirm;
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldDidChange:)
            name:UITextFieldTextDidChangeNotification object:_confirm];
    [self validate]; //Validate in case editing on confirm began before observer was set.
}

- (void) setQuery:(NSString *)query {
    _query = query;
}

- (void) textFieldDidChange:(NSNotification *)notification {
    NSLog(@"UPDATE");
    _isValid = [self validate];
    [self showInputValidation];
}

- (BOOL) validateRegex {
    if (_regex.length == 0) {
        return true;
    }
    return [NSArgumentValidator isValid:self.text withRegex:_regex];
}

- (BOOL) validateConfirm {
   // NSLog(@"%@ : %@", [_confirm text], self.text);
    if (_confirm == NULL) {
        //NSLog(@"IS NULL");
        return true;
    }
    return [self.text isEqualToString:_confirm.text];
}

- (BOOL) validateQuery {
    return true;
}

- (BOOL) validate {
    _isValid = (self.text == 0 && _isOptional) || ((self.text != 0) && [self validateRegex] && [self validateConfirm] && [self validateQuery]);
    return _isValid;
}

//IF ANYONE HAS A SOLUTION AS TO HOW TO MAKE CHANGING BORDER COLOR CHANGE THE COLOR ALONG THE ROUNDED BORDER THAT IS PRESENT AS OPPOSED TO A RECTANGULAR BORDER LET ME KNOW.
- (void) showInputValidation {
    self.layer.borderWidth = 1.0;
    if (self.text.length == 0) {
        self.layer.borderColor = [[UIColor blackColor] CGColor];
    } else if (_isValid) {
        self.layer.borderColor = [[UIColor greenColor] CGColor];
    } else {
        self.layer.borderColor = [[UIColor redColor] CGColor];
    }
}
- (void) finalize {
    [super finalize];
    [[NSNotificationCenter defaultCenter] removeObserver:self
            name:UITextFieldTextDidChangeNotification object:self];

    if (_confirm != NULL) {
        [[NSNotificationCenter defaultCenter] removeObserver:self
                name:UITextFieldTextDidChangeNotification object:_confirm];
    }
}

@end

Спасибо за помощь!


person nothingness    schedule 02.09.2014    source источник


Ответы (1)


Одна вопиющая ошибка в этом коде заключается в том, что вы устанавливаете регулярное выражение в cellForRowAtIndexPath:, хотя все ячейки повторно используют один и тот же объект ячейки. cellForRowAtIndexPath: следует использовать только для установки содержимого ячейки, например текста и цвета. Вместо этого создайте IBOutlet для проверяющих текстовых полей и добавьте их регулярные выражения в viewDidLoad. А еще лучше полностью отказаться от пользовательского подкласса и вместо этого запускать проверку регулярных выражений всякий раз, когда одно из соответствующих текстовых полей запускает событие после завершения редактирования.

person NRitH    schedule 05.09.2014
comment
Каждая ячейка, удаленная из очереди, отличается и имеет другой идентификатор. Я уверен, что мог бы исправить это таким образом, хотя и очень грязно, но я также хотел бы понять, почему это не работает так, как есть. - person nothingness; 05.09.2014
comment
Это связано с тем, что повторно используемые ячейки используются как резиновые штампы для рисования ячеек, а не для обработки бизнес-логики, лежащей в основе ячеек. Я не знаю точно, но я предполагаю, что когда вы устанавливаете регулярное выражение в одном вызове на dequeue, оно затирается или проверяемый текст затирается при следующем вызове dequeue. - person NRitH; 06.09.2014
comment
Я думаю, что теперь понимаю, поэтому, по сути, когда вы вызываете этот метод, он воссоздает ячейку по указанному индексу, а не извлекает фактическую отображаемую ячейку - или я неправильно понимаю? Есть ли способ получить фактическую ячейку? - person nothingness; 06.09.2014
comment
Круто, ну спасибо. Мне удалось исправить это, изменив представление таблицы, чтобы иметь статические ячейки и связать их все с IBOutlets. Затем я просто устанавливаю параметр подтверждения рассматриваемого текстового поля, ссылаясь на ячейку IBOutlet с текстовым полем, которое я хочу подтвердить. Спасибо за помощь! - person nothingness; 06.09.2014