В 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, текст поле никогда не спрашивается, он вынужден уйти в отставку".