РЕДАКТИРОВАТЬ
Смотрите мой ответ здесь для лучшего решения общего назначения, которое вы можете включить в любой проект.
ОРИГИНАЛЬНЫЙ ОТВЕТ
ДругоеОтветы предложили выполнить проверку в методах делегата текстового поля 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