Есть ли способ спросить у iOS, кто из ее детей имеет статус первого респондента?
В Mac OS X вы можете найти первого респондента следующим образом:
[[self window] firstResponder]
Есть ли способ сделать это в iOS? Или вам нужно перечислить дочерние элементы управления и отправить isFirstResponder
сообщение каждому?
4 ответа
Вам нужно будет перебрать все дочерние элементы управления и проверить isFirstResponder
имущество. Когда вы сталкиваетесь TRUE
вырваться из петли.
UIView *firstResponder;
for (UIView *view in self.view.subviews) //: caused error
{
if (view.isFirstResponder)
{
firstResponder = view;
break;
}
}
ЛУЧШЕЕ РЕШЕНИЕ
Смотрите ответ Якоба.
Мне действительно нравится решение VJK, но, как предполагает MattDiPasquale, оно кажется более сложным, чем необходимо. Итак, я написал эту более простую версию:
Objective-C
#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
Swift 4
import UIKit
extension UIResponder {
private static weak var _currentFirstResponder: UIResponder?
static var currentFirstResponder: UIResponder? {
_currentFirstResponder = nil
UIApplication.shared.sendAction(#selector(UIResponder.findFirstResponder(_:)), to: nil, from: nil, for: nil)
return _currentFirstResponder
}
@objc func findFirstResponder(_ sender: Any) {
UIResponder._currentFirstResponder = self
}
}
Я также сделал это методом класса, так как это казалось более логичным. Теперь вы можете найти первого респондента следующим образом: [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
Тогда в любом классе, который происходит от UIResponder
вы можете получить первый ответчик по телефону
UIResponder* aFirstResponder = [self currentFirstResponder];
но не забудьте сначала импортировать файл интерфейса категории UIResponder!
При этом используются документированные API, поэтому не должно быть проблем с отклонением в магазине приложений.
Если вам нужен первый респондент только для того, чтобы вы могли попросить его уйти в отставку, вот способ заставить любого уйти в отставку. В UIView есть метод, который будет перебирать все подпредставления UIViews и запрашивать всех, кто первым ответит, подать в отставку.
[[self view] endEditing:YES];
Вот ссылка на Apple UIView Docs: "Этот метод просматривает текущее представление и его иерархию подпредставления для текстового поля, которое в настоящее время является первым респондентом. Если он находит его, он просит это текстовое поле подать в отставку как первый респондент. Если сила для параметра установлено значение YES, текстовое поле даже не запрашивается; оно вынуждено уйти в отставку."