有没有办法询问iOS视图的哪个子级具有第一响应者状态?
在Mac OS X中,您可以找到如下第一响应者:有没有办法询问iOS视图的哪个子级具有第一响应者状态?,ios,cocoa-touch,uiresponder,responder-chain,Ios,Cocoa Touch,Uiresponder,Responder Chain,在Mac OS X中,您可以找到如下第一响应者: [[self window] firstResponder] 在iOS中有没有办法做到这一点?或者您需要枚举子控件并向每个子控件发送isFirstResponder消息吗?您需要迭代所有子控件并测试isFirstResponder属性。当你遇到TRUE时,打破循环 UIView *firstResponder; for (UIView *view in self.view.subviews) //: caused error { if
[[self window] firstResponder]
在iOS中有没有办法做到这一点?或者您需要枚举子控件并向每个子控件发送
isFirstResponder
消息吗?您需要迭代所有子控件并测试isFirstResponder
属性。当你遇到TRUE
时,打破循环
UIView *firstResponder;
for (UIView *view in self.view.subviews) //: caused error
{
if (view.isFirstResponder)
{
firstResponder = view;
break;
}
}
更好的解决方案
请参阅。如果您需要第一响应者,这样您就可以要求其辞职,这里有一种方法可以让任何人辞职。UIView有一个方法,该方法将迭代所有UIView子视图,并要求任何第一响应者辞职
[[self view] endEditing:YES];
这是一个
此方法查看当前作为第一响应者的文本字段的当前视图及其子视图层次结构。如果找到一个文本字段,它将要求该文本字段辞去第一响应者的职务。如果force参数设置为YES,则从未要求该文本字段;它将被迫辞去职务我在
UIResponder
上写了一个类别来查找第一个响应者
@interface UIResponder (firstResponder)
- (id) currentFirstResponder;
@end
及
但请记住首先导入UIResponder类别接口文件
这使用了有文档记录的API,因此不会出现应用商店拒绝问题。我非常喜欢,但正如MattDiPasquale所说,这似乎比必要的复杂。所以我写了一个更简单的版本:
目标-C
斯威夫特4
我还将其作为一种类方法,因为这似乎更有意义。您现在可以像这样找到第一响应者:[UIResponder currentFirstResponder]
我不认为OP想强迫它辞去第一响应者的职务,只是为了找到第一响应者。然而,这是一个让人们发现这个片段的好地方。使用
-[UIApplication sendAction:to:from:forEvent:
很好!)但是,与其使用关联对象引用第一响应者
,为什么不使用静态变量,因为一次只有一个第一响应者
?哦,这太聪明了!在阅读文档之前,我无法发送您的发送操作:
。这必须是iOS API中唯一一个实际允许直接访问第一响应者的部分。只返回询问当前第一响应者的视图。当我检查响应程序是否是预期的第一响应程序时,它会说“没有”。此片段只搜索视图的直接后代,但在嵌套更深时找不到第一响应程序。这非常简单,做得很好。instancetype非常适合:)fwiw:视图控制器可以成为第一响应程序。您只需从返回YES
——即可成为第一响应者。这对于始终在屏幕上的输入附件视图或处理快捷方式(即使没有聚焦视图)非常有用。因此,在这里使用UIView*
是错误的。下面是一个快速实现:至少在iOS9上不起作用。我将焦点放在滚动视图中的文本字段中。在我按照描述的方式检查firstResponder
之后,我将ScrollView作为第一响应者。同时,[[[UIApplication sharedApplication]windows]firstObject]valueForKey:@“firstResponder”]
给出了文本字段。
#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* aFirstResponder = [self currentFirstResponder];
#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
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
}
}