46 votes

Existe-t-il un moyen de demander à une vue iOS lequel de ses enfants a le statut de premier intervenant ?

Sous Mac OS X, vous pouvez trouver le premier répondeur comme ceci :

 [[self window] firstResponder]

Y a-t-il un moyen de le faire dans iOS ? Ou devez-vous énumérer les contrôles enfants et envoyer un message isFirstResponder à chacun ?

251voto

Jakob Egger Points 4282

J'aime beaucoup la solution de VJK , mais comme le suggère MattDiPasquale, elle semble plus complexe que nécessaire. J'ai donc écrit cette version plus simple :

Objectif 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

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

J'en ai également fait une méthode de classe car cela semblait avoir plus de sens. Vous pouvez maintenant trouver le premier répondant comme ceci : [UIResponder currentFirstResponder]


26voto

VJK Points 191

J'ai écrit une catégorie sur UIResponder pour trouver le premier répondant

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

et

 #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

Ensuite, dans n'importe quelle classe qui dérive d'un UIResponder vous pouvez obtenir le premier intervenant en appelant

 UIResponder* aFirstResponder = [self currentFirstResponder];

mais n'oubliez pas d'importer d'abord le fichier d'interface de catégorie UIResponder !

Cela utilise des API documentées, il ne devrait donc y avoir aucun problème de rejet de l'App Store.

12voto

Evan Mulawski Points 28536

Vous devrez parcourir tous les contrôles enfants et tester la propriété isFirstResponder Lorsque vous rencontrez TRUE , sortez de la boucle.

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

MEILLEURE SOLUTION

Voir la réponse de Jakob .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X