在 Mac OS X 中,您可以通过以下方式查找第一响应者:
[[self window] firstResponder]
在iOS中有没有方法可以做到这一点?或者你需要枚举子控件并向每个控件发送一个isFirstResponder
消息吗?
在 Mac OS X 中,您可以通过以下方式查找第一响应者:
[[self window] firstResponder]
在iOS中有没有方法可以做到这一点?或者你需要枚举子控件并向每个控件发送一个isFirstResponder
消息吗?
我真的很喜欢VJK的解决方案,但像MattDiPasquale建议的那样,它似乎比必要的要复杂。所以我写了这个更简单的版本:
UIResponder+FirstResponder.h:
#import <UIKit/UIKit.h>
@interface UIResponder (FirstResponder)
+(id)currentFirstResponder;
@end
UIResponder+FirstResponder.m:
#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
}
}
我觉得把它变成一个类方法更有意义,你现在可以这样找到第一响应者:[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,所以不应该有应用商店拒绝问题。
-[UIApplication sendAction:to:from:forEvent:]
很方便!:) 但是,为什么不使用静态变量来引用 firstResponder
呢?因为一次只会有一个 firstResponder
,所以不需要使用关联对象。 - ma11hew28sendAction:
。那一定是 iOS API 中唯一直接访问第一响应者的部分。 - sobri如果你需要第一个响应者对象仅仅是为了让它放弃响应者的状态,那么这里有一种方法可以使得任何一个响应者放弃其状态。UIView有一个方法可以迭代所有子视图,并要求任何第一个响应者放弃其状态。
[[self view] endEditing:YES];
这里有一个指向苹果UIView文档的链接 "该方法查找当前视图及其子视图层次结构中当前是第一响应者的文本字段。如果找到,则请求该文本字段放弃作为第一响应者的身份。如果force参数设置为YES,则不会询问文本字段,而是强制其放弃第一响应者身份。"
isFirstResponder
属性。当你遇到 TRUE
时,退出循环。UIView *firstResponder;
for (UIView *view in self.view.subviews) //: caused error
{
if (view.isFirstResponder)
{
firstResponder = view;
break;
}
}
更好的解决方案
请参考Jakob的答案。
-canBecomeFirstResponder
方法中返回YES
。这对于始终在屏幕上或处理快捷方式而没有视图聚焦的输入附件视图非常有用。因此,在此处使用UIView *
是错误的。 - Max Seelemann