iphone-是否有任何方法可以让iOS查看哪个子级具有第一响应者身份?

这个问题已经在这里有了答案:

  • 在不使用私有API的情况下获取当前的第一响应者 28个答案

在Mac OS X中,您可以找到第一个响应者,如下所示:

[[self window] firstResponder]

在iOS中有什么方法吗? 还是需要枚举子控件并向每个控件发送isFirstResponder消息?

Tommy Herbert asked 2020-07-31T19:12:09Z
4个解决方案
233 votes

我真的很喜欢VJK的解决方案,但是正如MattDiPasquale所建议的那样,这似乎比需要的更为复杂。 所以我写了这个简单的版本:

目标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

斯威夫特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]


Jakob Egger answered 2020-07-31T19:24:24Z
26 votes

我在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,因此应该没有应用商店拒绝问题。

VJK answered 2020-07-31T19:25:01Z
11 votes

您将需要遍历所有子控件并测试isFirstResponder属性。 当您遇到TRUE时,请跳出循环。

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

更好的解决方案

参见雅各布的答案。

Evan Mulawski answered 2020-07-31T19:23:50Z
11 votes

如果您只需要第一响应者,以便您可以要求其辞职,这是一种让任何人辞职的方法。 UIView具有一种方法,该方法将遍历所有UIViews子视图,并要求任何第一响应者退出。

[[self view] endEditing:YES];

这是Apple的UIView文档的链接“此方法查看当前作为第一响应者的文本字段的当前视图及其子视图层次结构。如果找到该方法,它将要求该文本字段放弃作为第一响应者。如果force参数设置为YES,则文本 甚至从来没有问过这个领域;它被迫辞职。”

Praxiteles answered 2020-07-31T19:25:26Z
translate from https://stackoverflow.com:/questions/5029267/is-there-any-way-of-asking-an-ios-view-which-of-its-children-has-first-responder