Есть ли способ спросить мнение iOS, у которого у его детей статус первого ответчика?

В Mac OS X вы можете найти первого ответчика следующим образом:

[[self window] firstResponder]

Есть ли способ сделать это в iOS? Или вам нужно перечислить дочерние элементы управления и отправить сообщение isFirstResponder каждому из них?

Ответ 1

Вам нужно будет перебрать все дочерние элементы управления и проверить свойство isFirstResponder. Когда вы встретите TRUE, выйдите из цикла.

UIView *firstResponder;
for (UIView *view in self.view.subviews) //: caused error
{
    if (view.isFirstResponder)
    {
        firstResponder = view;
        break;
    }
}

ЛУЧШЕЕ РЕШЕНИЕ

См. ответ Якоба.

Ответ 2

Мне действительно нравится решение 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]

Ответ 3

Я написал категорию на 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, поэтому не должно быть проблем с отказом магазина приложений.

Ответ 4

Если вам нужен первый ответчик, чтобы вы могли попросить его уйти в отставку, вот подход, чтобы заставить любого уйти в отставку. У UIView есть метод, который будет выполнять итерацию по всем областям UIViews и спросить всех, кто первым отвечает, чтобы уйти в отставку.

[[self view] endEditing:YES];

Вот ссылка на документы Apple UIView "Этот метод просматривает текущее представление и его иерархию подчинения для текстового поля, которое в настоящее время является первым ответчиком. Если он находит его, он просит, чтобы текстовое поле ушло в отставку в качестве первого ответчика. Если параметр force установлен в YES, текст поле никогда не спрашивается, он вынужден уйти в отставку".