Вызов функции на ощупь за пределами активного UITextField - PullRequest
1 голос
/ 12 января 2012

Как вызвать пользовательскую функцию, когда пользователь касается вне UITextField с фокусом клавиатуры?

Моя цель - вызвать функцию для проверки текстового поля.

Я пробовал это:

// Dismiss Keyboard

- (void)touchesEnded: (NSSet *)touches withEvent: (UIEvent *)event {
    for (UIView* view in self.view.subviews) {
        if ([view isKindOfClass:[UITextField class]]) 
        {
            [view resignFirstResponder];
            [self validationForNoOfPassengers];
        }

    }
}

validationForNoOfPassengers - мой метод проверки на валидацию. Проблема здесь в том, что когда я нажимаю на другие элементы управления пользовательского интерфейса, он не вызывает вышеуказанный метод. Вышеуказанный метод вызывается только при касании снаружи на экране (но не в UIcontrols). Любое руководство?

Ответы [ 4 ]

2 голосов
/ 12 января 2012

РЕДАКТИРОВАТЬ

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

ОРИГИНАЛЬНЫЙ ОТВЕТ

ДругоеОтветы предложили выполнить проверку в методах делегата текстового поля textFieldShouldEndEditing: или textFieldDidEndEditing:.Как вы обнаружили, когда вы прикасаетесь к элементу управления, ваше текстовое поле не отправляет эти сообщения его делегату.

Оно не отправляет эти сообщения, поскольку оно не завершает редактирование.Текстовое поле остается первым респондентом (фокус клавиатуры), когда вы касаетесь другого нетекстового элемента управления.

Я не знаю, есть ли у вас одно или два текстовых поля, которые имеют проверку, или много текстовых полейкоторые имеют проверки.Я не знаю, есть ли у вас один или два нетекстовых элемента управления или много нетекстовых элементов управления.Лучшее решение для вас действительно зависит от того, что у вас есть.

Что вы действительно хотели бы сделать, это проверять, при каждом новом касании, есть ли первый респондент, если да, то, является ли новое касаниевне первого ответчика.Если это так, отправьте resignFirstResponder текущему первому респонденту (что заставит его отправить textFieldShouldEndEditing: своему делегату) и продолжите работу, только если resignFirstResponder вернет ДА.

Если у вас есть только одно текстовое поле,вы можете сделать ваше представление верхнего уровня подклассом UIView и переопределить метод hitTest:withEvent:, например:

MyView.h

#import <UIKit/UIKit.h>
@interface MyView : UIView
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end

MyView.m

#import "MyView.h"
@implementation MyView
@synthesize textField;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    return (hitView != self.textField
        && self.textField.isFirstResponder
        && ![self.textField resignFirstResponder])
        ? nil : hitView;
}
@end

Оказывается, что hitTest:withEvent: на самом деле вызывается несколько раз (три в моем тестировании) за касание.Таким образом, вы не просто хотите представить предупреждение в textFieldShouldEndEditing:, если проверка не удалась - вам нужно отслеживать, отображается ли предупреждение уже на экране.В противном случае вы увидите, что предупреждение будет всплывать несколько раз.

Приведенный выше метод будет безобразным, если у вас есть несколько текстовых полей.Вам нужно будет проверить каждый из них, чтобы увидеть, является ли он первым респондентом, а не сенсорным представлением.Было бы гораздо проще, если бы вы просто запросили у системы текущий первый респондент.

Существует метод, который возвращает текущего первого респондента: вы можете отправить firstResponder на [[UIApplication sharedApplication] keyWindow], чтобы получить текущийпервый респондент (или ноль, если нет первого респондента). К сожалению , сообщение firstResponder является публичным API.Если вы используете его, вас могут не пустить в App Store.

Если вы решите, что хотите его использовать, вот что вы вставили в MyView.m:

MyView.m (исправлено)

#import "MyView.h"

@protocol MyViewFirstResponderProtocol
// Have to declare the message so the compiler will allow it.
- (UIResponder *)firstResponder;
@end

@implementation MyView
@synthesize textField;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"hitTest for event %@", event);
    UIView *hitView = [super hitTest:point withEvent:event];
    UIResponder *firstResponder = [(id)self.window firstResponder];
    return (firstResponder
        && hitView != firstResponder
        && ![firstResponder resignFirstResponder])
        ? nil : hitView;
}
@end
2 голосов
/ 12 января 2012

Установите ваш контроллер представления (или некоторый другой объект) как делегат текстового поля. Выполните проверку в -textFieldShouldEndEditing: или -textFieldDidEndEditing:.

0 голосов
/ 12 января 2012

Попробуйте переопределить resignFirstResponder и выполнить там проверку.

0 голосов
/ 12 января 2012

Установите делегата в текстовое поле и реализуйте метод textFieldDidEndEditing: (в классе, который соответствует протоколу UITextFieldDelegate ) и вызовите в нем свою функцию:

void
do_something(void)
{
    return;
}

/* ... */

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    do_something();
}
...