Is there any way of asking an iOS view which of its children has first responder status? [duplicate]

青春壹個敷衍的年華 提交于 2019-11-26 14:59:34

问题


In Mac OS X, you can find the first responder like this:

[[self window] firstResponder]

Is there any way of doing it in iOS? Or do you need to enumerate the child controls and send an isFirstRespondermessage to each one?


回答1:


You would need to iterate over all of the child controls and test the isFirstResponder property. When you encounter TRUE, break out of the loop.

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

BETTER SOLUTION

See Jakob's answer.




回答2:


I really like VJK's solution, but as MattDiPasquale suggests it seems more complex than necessary. So I wrote this simpler version:

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
    }
}

I also made it a class method since that seemed to make more sense. You can now find the first responder like so: [UIResponder currentFirstResponder]





回答3:


I wrote a category on UIResponder to find the first responder

@interface UIResponder (firstResponder)
- (id) currentFirstResponder;
@end

and

#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

Then in any class that derives from a UIResponder you can get the first responder by calling

UIResponder* aFirstResponder = [self currentFirstResponder];

but remember to import the UIResponder category interface file first!

This uses documented API's so there should be no app store rejection issues.




回答4:


If you need first responder just so you can ask it to resign its status, here is an approach to get any to resign. UIView has a method that will iterate through all of UIViews subviews and ask any that are first responder to resign.

[[self view] endEditing:YES];

Here is a link to Apple's UIView Docs "This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign."



来源:https://stackoverflow.com/questions/5029267/is-there-any-way-of-asking-an-ios-view-which-of-its-children-has-first-responder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!