В Mac OS X вы можете найти первого ответчика следующим образом:
[[self window] firstResponder]
Есть ли способ сделать это в iOS? Или вам нужно перечислить дочерние элементы управления и отправить сообщение isFirstResponder
каждому из них?
В Mac OS X вы можете найти первого ответчика следующим образом:
[[self window] firstResponder]
Есть ли способ сделать это в iOS? Или вам нужно перечислить дочерние элементы управления и отправить сообщение isFirstResponder
каждому из них?
Вам нужно будет перебрать все дочерние элементы управления и проверить свойство isFirstResponder
. Когда вы встретите TRUE
, выйдите из цикла.
UIView *firstResponder;
for (UIView *view in self.view.subviews) //: caused error
{
if (view.isFirstResponder)
{
firstResponder = view;
break;
}
}
ЛУЧШЕЕ РЕШЕНИЕ
См. ответ Якоба.
Мне действительно нравится решение VJK, но, как утверждает MattDiPasquale, это кажется более сложным, чем необходимо. Поэтому я написал эту более простую версию:
#import "UIResponder+FirstResponder.h"
static __weak id currentFirstResponder;
@implementation UIResponder (FirstResponder)
+(id)currentFirstResponder {
currentFirstResponder = nil;
[[UIApplication sharedApplication] sendAction:@selector(findFirstResponder:) to:nil from:nil forEvent:nil];
return currentFirstResponder;
}
-(void)findFirstResponder:(id)sender {
currentFirstResponder = self;
}
@end
Я также сделал это классным методом, поскольку это, казалось, имело больше смысла. Теперь вы можете найти первого ответчика следующим образом: [UIResponder currentFirstResponder]
Я написал категорию на UIResponder
, чтобы найти первого ответчика
@interface UIResponder (firstResponder)
- (id) currentFirstResponder;
@end
и
#import <objc/runtime.h>
#import "UIResponder+firstResponder.h"
static char const * const aKey = "first";
@implementation UIResponder (firstResponder)
- (id) currentFirstResponder {
[[UIApplication sharedApplication] sendAction:@selector(findFirstResponder:) to:nil from:self forEvent:nil];
id obj = objc_getAssociatedObject (self, aKey);
objc_setAssociatedObject (self, aKey, nil, OBJC_ASSOCIATION_ASSIGN);
return obj;
}
- (void) setCurrentFirstResponder:(id) aResponder {
objc_setAssociatedObject (self, aKey, aResponder, OBJC_ASSOCIATION_ASSIGN);
}
- (void) findFirstResponder:(id) sender {
[sender setCurrentFirstResponder:self];
}
@end
Тогда в любом классе, который происходит от a UIResponder
, вы можете получить первого ответчика, вызвав
UIResponder* aFirstResponder = [self currentFirstResponder];
но не забудьте сначала импортировать файл интерфейса категории UIResponder!
Это использует документированный API, поэтому не должно быть проблем с отказом магазина приложений.
Если вам нужен первый ответчик, чтобы вы могли попросить его уйти в отставку, вот подход, чтобы заставить любого уйти в отставку. У UIView есть метод, который будет выполнять итерацию по всем областям UIViews и спросить всех, кто первым отвечает, чтобы уйти в отставку.
[[self view] endEditing:YES];
Вот ссылка на документы Apple UIView "Этот метод просматривает текущее представление и его иерархию подчинения для текстового поля, которое в настоящее время является первым ответчиком. Если он находит его, он просит, чтобы текстовое поле ушло в отставку в качестве первого ответчика. Если параметр force установлен в YES, текст поле никогда не спрашивается, он вынужден уйти в отставку".