Uzyskaj aktualną pierwszą odpowiedź bez korzystania z prywatnego interfejsu API

Wysłałem swoją aplikację nieco ponad tydzień temu i dostałem dzisiaj przerażający e-mail z odrzuceniem. Mówi mi, że moja aplikacja nie może zostać zaakceptowana, ponieważ używam Niepublicznego API; w szczególności mówi,

Niepubliczne API, które jest zawarte w aplikacji jest firstResponder.

Teraz, obrażające wywołanie API jest w rzeczywistości rozwiązaniem, które znalazłem tutaj na SO:

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView   *firstResponder = [keyWindow performSelector:@selector(firstResponder)];

Jak wyświetlić na ekranie aktualną pierwszą odpowiedź? Szukam sposobu, który nie dostanie mojej aplikacji odrzucony.

Author: Mark Amery, 2009-12-01

25 answers

W jednej z moich aplikacji często chcę, aby pierwszy respondent zrezygnował, jeśli użytkownik dotknie w tle. W tym celu napisałem kategorię na UIView, którą nazywam na UIWindow.

Na tej podstawie przedstawiono poniżej i należy zwrócić osobę, która udzieliła pierwszej odpowiedzi.

@implementation UIView (FindFirstResponder)
- (id)findFirstResponder
{
    if (self.isFirstResponder) {
        return self;        
    }
    for (UIView *subView in self.subviews) {
        id responder = [subView findFirstResponder];
        if (responder) return responder;
    }
    return nil;
}
@end

IOS 7+

- (id)findFirstResponder
{
    if (self.isFirstResponder) {
        return self;
    }
    for (UIView *subView in self.view.subviews) {
        if ([subView isFirstResponder]) {
            return subView;
        }
    }
    return nil;
}

Swift:

extension UIView {
    var firstResponder: UIView? {
        guard !isFirstResponder else { return self }

        for subview in subviews {
            if let firstResponder = subview.firstResponder {
                return firstResponder
            }
        }

        return nil
    }
}

Przykład użycia w języku Swift:

if let firstResponder = view.window?.firstResponder {
    // do something with `firstResponder`
}
 314
Author: Thomas Müller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-23 15:56:33

Jeśli twoim ostatecznym celem jest rezygnacja z pierwszej odpowiedzi, powinno to zadziałać: [self.view endEditing:YES]

 522
Author: cdyson37,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-11 12:25:56

Powszechnym sposobem manipulowania ratownikiem jest użycie zero ukierunkowanych działań. Jest to sposób wysyłania dowolnej wiadomości do łańcucha odpowiedzi (zaczynając od pierwszego odpowiedzi) i kontynuowania łańcucha aż ktoś odpowie na wiadomość(zaimplementował metodę pasującą do selektora).

W przypadku odrzucenia klawiatury jest to najskuteczniejszy sposób, który będzie działał bez względu na to, które okno lub widok jest pierwszą odpowiedzią:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

To powinno być bardziej skuteczne niż nawet [self.view.window endEditing:YES].

(podziękowania dla BigZaphod za przypomnienie mi koncepcji)

 175
Author: nevyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-01 22:05:57

Oto kategoria, która pozwala szybko znaleźć pierwszego ratownika dzwoniąc [UIResponder currentFirstResponder]. Wystarczy dodać dwa następujące pliki do projektu:

UIResponder+FirstResponder.h

#import <Cocoa/Cocoa.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
Sztuczka polega na tym, że wysłanie akcji do nil wysyła ją do pierwszego ratownika.

(pierwotnie opublikowałem tę odpowiedź tutaj: https://stackoverflow.com/a/14135456/322427 )

 88
Author: Jakob Egger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:31

Oto rozszerzenie zaimplementowane w Swift oparte na najdoskonalszej odpowiedzi Jakoba Eggera:

import UIKit

extension UIResponder {
    // Swift 1.2 finally supports static vars!. If you use 1.1 see: 
    // http://stackoverflow.com/a/24924535/385979
    private weak static var _currentFirstResponder: UIResponder? = nil

    public class func currentFirstResponder() -> UIResponder? {
        UIResponder._currentFirstResponder = nil
        UIApplication.sharedApplication().sendAction("findFirstResponder:", to: nil, from: nil, forEvent: nil)
        return UIResponder._currentFirstResponder
    }

    internal func findFirstResponder(sender: AnyObject) {
        UIResponder._currentFirstResponder = self
    }
}

Swift 4

import UIKit    

extension UIResponder {
    private weak static var _currentFirstResponder: UIResponder? = nil

    public static var current: UIResponder? {
        UIResponder._currentFirstResponder = nil
        UIApplication.shared.sendAction(#selector(findFirstResponder(sender:)), to: nil, from: nil, for: nil)
        return UIResponder._currentFirstResponder
    }

    @objc internal func findFirstResponder(sender: AnyObject) {
        UIResponder._currentFirstResponder = self
    }
}
 34
Author: Code Commander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 19:15:27

Nie jest ładny, ale sposób w jaki rezygnuję z pierwszej odpowiedzi, Gdy Nie wiem, co to jest Odpowiedź:

Utwórz pole UITextField w IB lub programowo. Ukryj to. Podlinkuj go do swojego kodu, jeśli zrobiłeś to w IB.

Następnie, gdy chcesz zwolnić klawiaturę, przełączasz responder na niewidoczne pole tekstowe i natychmiast rezygnujesz z niego:

    [self.invisibleField becomeFirstResponder];
    [self.invisibleField resignFirstResponder];
 29
Author: cannyboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-24 18:33:29

Dla wersji Swift 3 i 4nevyn ' S ODPOWIEDŹ:

UIApplication.shared.sendAction(#selector(UIView.resignFirstResponder), to: nil, from: nil, for: nil)
 12
Author: Pochi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-03 02:45:28

Oto rozwiązanie, które zgłasza poprawnego ratownika (wiele innych rozwiązań nie zgłasza na przykład UIViewController jako ratownika), nie wymaga zapętlania hierarchii widoku i nie używa prywatnych interfejsów API.

Wykorzystuje metodę Apple sendAction:to:from:forEvent: , która już wie, jak uzyskać dostęp do osoby udzielającej pierwszej pomocy.

Po prostu musimy to poprawić na 2 sposoby:

  • Extend UIResponder tak aby mógł wykonać nasz własny kod na pierwszym / align = "left" /
  • podklasa UIEvent w celu zwrócenia pierwszej odpowiedzi.

Oto kod:

@interface ABCFirstResponderEvent : UIEvent
@property (nonatomic, strong) UIResponder *firstResponder;
@end

@implementation ABCFirstResponderEvent
@end

@implementation UIResponder (ABCFirstResponder)
- (void)abc_findFirstResponder:(id)sender event:(ABCFirstResponderEvent *)event {
    event.firstResponder = self;
}
@end

@implementation ViewController

+ (UIResponder *)firstResponder {
    ABCFirstResponderEvent *event = [ABCFirstResponderEvent new];
    [[UIApplication sharedApplication] sendAction:@selector(abc_findFirstResponder:event:) to:nil from:nil forEvent:event];
    return event.firstResponder;
}

@end
 10
Author: Senseful,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-07 01:54:55

Pierwszą odpowiedzią może być dowolna instancja klasy UIResponder, więc istnieją inne klasy, które mogą być pierwszą odpowiedzią pomimo UIViews. Na przykład UIViewController może być również pierwszą odpowiedzią.

W ten gist znajdziesz rekurencyjny sposób uzyskania pierwszego odpowiedzi poprzez zapętlenie hierarchii kontrolerów zaczynając od kontrolera rootViewController w oknach aplikacji.

Możesz pobrać wtedy pierwszą odpowiedź przez doing

- (void)foo
{
    // Get the first responder
    id firstResponder = [UIResponder firstResponder];

    // Do whatever you want
    [firstResponder resignFirstResponder];      
}

Jednakże, jeśli first responder nie jest podklasą UIView lub UIViewController, takie podejście zakończy się niepowodzeniem.

Aby rozwiązać ten problem, możemy zrobić inne podejście, tworząc kategorię na UIResponder i wykonać magiczne świstanie, aby móc zbudować tablicę wszystkich żywych instancji tej klasy. Następnie, aby uzyskać pierwszą odpowiedź, możemy łatwo iterację i zapytać każdy obiekt, czy -isFirstResponder.

To podejście można znaleźć zaimplementowane w tej drugiej gist .

Mam nadzieję, że to pomoże.
 7
Author: vilanovi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-23 16:54:28

Używając Swift i z specyficznym UIView obiektem może to pomóc:

func findFirstResponder(inView view: UIView) -> UIView? {
    for subView in view.subviews as! [UIView] {
        if subView.isFirstResponder() {
            return subView
        }

        if let recursiveSubView = self.findFirstResponder(inView: subView) {
            return recursiveSubView
        }
    }

    return nil
}

Po prostu umieść go w swoim UIViewController i użyj go w ten sposób:

let firstResponder = self.findFirstResponder(inView: self.view)

Zwróć uwagę, że wynik jest opcjonalną wartością , więc będzie to nil, jeśli w podwiach podanymi widokami nie znaleziono firstResponser.

 6
Author: Dschee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-23 21:30:29

Przeanalizuj widoki, które mogą być pierwszą odpowiedzią i użyj - (BOOL)isFirstResponder, aby określić, czy aktualnie są.

 5
Author: Johan Kool,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-01 00:37:04

Peter Steinberger właśnie napisał na Twitterze o prywatnym powiadomieniu UIWindowFirstResponderDidChangeNotification, które możesz obserwować, jeśli chcesz oglądać zmianę pierwszyresponder.

 4
Author: Heath Borders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-07 14:55:33

Jeśli musisz tylko zabić klawiaturę, gdy użytkownik dotknie obszaru tła, dlaczego nie dodać rozpoznawania gestów i użyć go do wysłania wiadomości [[self view] endEditing:YES]?

Możesz dodać rozpoznawacz gestów stukania w pliku xib lub storyboard i podłączyć go do akcji,

Wygląda coś takiego, a potem skończone

- (IBAction)displayGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer{
     [[self view] endEditing:YES];
}
 4
Author: Arkadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-27 11:48:34

To właśnie zrobiłem, aby znaleźć to, co UITextField jest pierwszym responderem, gdy użytkownik kliknie Zapisz/Anuluj w ModalViewController:

    NSArray *subviews = [self.tableView subviews];

for (id cell in subviews ) 
{
    if ([cell isKindOfClass:[UITableViewCell class]]) 
    {
        UITableViewCell *aCell = cell;
        NSArray *cellContentViews = [[aCell contentView] subviews];
        for (id textField in cellContentViews) 
        {
            if ([textField isKindOfClass:[UITextField class]]) 
            {
                UITextField *theTextField = textField;
                if ([theTextField isFirstResponder]) {
                    [theTextField resignFirstResponder];
                }

            }
        }

    }

}
 3
Author: Romeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-10 00:08:55

Just it case here is Swift version of awesome Jakob Egger ' s approach:

import UIKit

private weak var currentFirstResponder: UIResponder?

extension UIResponder {

    static func firstResponder() -> UIResponder? {
        currentFirstResponder = nil
        UIApplication.sharedApplication().sendAction(#selector(self.findFirstResponder(_:)), to: nil, from: nil, forEvent: nil)
        return currentFirstResponder
    }

    func findFirstResponder(sender: AnyObject) {
        currentFirstResponder = self
    }

}
 3
Author: Valentin Shergin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-27 21:13:03

Oto co mam w kategorii UIViewController. Przydatne do wielu rzeczy, w tym uzyskania pierwszej pomocy. Klocki są świetne!

- (UIView*) enumerateAllSubviewsOf: (UIView*) aView UsingBlock: (BOOL (^)( UIView* aView )) aBlock {

 for ( UIView* aSubView in aView.subviews ) {
  if( aBlock( aSubView )) {
   return aSubView;
  } else if( ! [ aSubView isKindOfClass: [ UIControl class ]] ){
   UIView* result = [ self enumerateAllSubviewsOf: aSubView UsingBlock: aBlock ];

   if( result != nil ) {
    return result;
   }
  }
 }    

 return nil;
}

- (UIView*) enumerateAllSubviewsUsingBlock: (BOOL (^)( UIView* aView )) aBlock {
 return [ self enumerateAllSubviewsOf: self.view UsingBlock: aBlock ];
}

- (UIView*) findFirstResponder {
 return [ self enumerateAllSubviewsUsingBlock:^BOOL(UIView *aView) {
  if( [ aView isFirstResponder ] ) {
   return YES;
  }

  return NO;
 }];
}
 2
Author: Andrei Tchijov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-24 05:32:09

Z kategorią na UIResponder, można legalnie poprosić obiekt UIApplication, Aby powiedział, Kto jest pierwszą osobą odpowiedzialną.

Zobacz to:

Czy jest jakiś sposób, aby zapytać widok iOS, które z jego dzieci ma status pierwszej odpowiedzi?

 2
Author: VJK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:46

Możesz spróbować również tak:

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event { 

    for (id textField in self.view.subviews) {

        if ([textField isKindOfClass:[UITextField class]] && [textField isFirstResponder]) {
            [textField resignFirstResponder];
        }
    }
} 

Nie próbowałem, ale wydaje się dobre rozwiązanie

 1
Author: Frade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-01 09:44:53

Rozwiązanie z romeo https://stackoverflow.com/a/2799675/661022 jest spoko, ale zauważyłem, że kod potrzebuje jeszcze jednej pętli. Pracowałem z tableViewController. Edytowałem scenariusz, a potem sprawdziłem. Wszystko działało idealnie.

Polecam spróbować:
- (void)findFirstResponder
{
    NSArray *subviews = [self.tableView subviews];
    for (id subv in subviews )
    {
        for (id cell in [subv subviews] ) {
            if ([cell isKindOfClass:[UITableViewCell class]])
            {
                UITableViewCell *aCell = cell;
                NSArray *cellContentViews = [[aCell contentView] subviews];
                for (id textField in cellContentViews)
                {
                    if ([textField isKindOfClass:[UITextField class]])
                    {
                        UITextField *theTextField = textField;
                        if ([theTextField isFirstResponder]) {
                            NSLog(@"current textField: %@", theTextField);
                            NSLog(@"current textFields's superview: %@", [theTextField superview]);
                        }
                    }
                }
            }
        }
    }
}
 1
Author: pedrouan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:31

To dobry kandydat do rekurencji! Nie trzeba dodawać kategorii do UIView.

Użycie (z kontrolera widoku):

UIView *firstResponder = [self findFirstResponder:[self view]];

Kod:

// This is a recursive function
- (UIView *)findFirstResponder:(UIView *)view {

    if ([view isFirstResponder]) return view; // Base case

    for (UIView *subView in [view subviews]) {
        if ([self findFirstResponder:subView]) return subView; // Recursion
    }
    return nil;
}
 1
Author: Pétur Ingi Egilsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-23 08:31:27

Możesz wywołać privite api w ten sposób, Apple ignoruj:

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
SEL sel = NSSelectorFromString(@"firstResponder");
UIView   *firstResponder = [keyWindow performSelector:sel];
 1
Author: ibcker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 10:11:27

Chciałbym podzielić się z wami moją implementacją dla find first responder w dowolnym miejscu UIView. Mam nadzieję, że to pomoże i przepraszam za mój angielski. Dzięki

+ (UIView *) findFirstResponder:(UIView *) _view {

UIView *retorno;

for (id subView in _view.subviews) {

    if ([subView isFirstResponder])
        return subView;

    if ([subView isKindOfClass:[UIView class]]) {
        UIView *v = subView;

        if ([v.subviews count] > 0) {
            retorno = [self findFirstResponder:v];
            if ([retorno isFirstResponder]) {
                return retorno;
            }
        }
    }
}

return retorno;

}

 1
Author: Rubens Iotti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-22 12:21:56

Swift version of @Thomas-müller 's response

extension UIView {

    func firstResponder() -> UIView? {
        if self.isFirstResponder() {
            return self
        }

        for subview in self.subviews {
            if let firstResponder = subview.firstResponder() {
                return firstResponder
            }
        }

        return nil
    }

}
 1
Author: Kádi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:30

Kod poniżej działa.

- (id)ht_findFirstResponder
{
    //ignore hit test fail view
    if (self.userInteractionEnabled == NO || self.alpha <= 0.01 || self.hidden == YES) {
        return nil;
    }
    if ([self isKindOfClass:[UIControl class]] && [(UIControl *)self isEnabled] == NO) {
        return nil;
    }

    //ignore bound out screen
    if (CGRectIntersectsRect(self.frame, [UIApplication sharedApplication].keyWindow.bounds) == NO) {
        return nil;
    }

    if ([self isFirstResponder]) {
        return self;
    }

    for (UIView *subView in self.subviews) {
        id result = [subView ht_findFirstResponder];
        if (result) {
            return result;
        }
    }
    return nil;
}   
 0
Author: John Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-15 13:27:41

Aktualizacja: myliłem się. Możesz rzeczywiście użyć UIApplication.shared.sendAction(_:to:from:for:), aby zadzwonić do pierwszego ratownika pokazanego w tym linku: http://stackoverflow.com/a/14135456/746890 .


Większość odpowiedzi tutaj nie może tak naprawdę znaleźć bieżącego ratownika, jeśli nie znajduje się w hierarchii widoku. Na przykład AppDelegate lub UIViewController podklasy.

Istnieje sposób, aby zagwarantować, że go znajdziesz, nawet jeśli obiekt pierwszej odpowiedzi nie jest UIView.

Najpierw zaimplementujmy jego odwróconą wersję, korzystanie z własności next UIResponder:

extension UIResponder {
    var nextFirstResponder: UIResponder? {
        return isFirstResponder ? self : next?.nextFirstResponder
    }
}

Z tą obliczoną właściwością, możemy znaleźć aktualną pierwszą odpowiedź od dołu do góry, nawet jeśli nie jest to UIView. Na przykład, od view do UIViewController, kto nim zarządza, jeśli kontroler widoku jest pierwszą osobą odpowiedzialną.

Jednak nadal potrzebujemy odgórnej rozdzielczości, pojedynczego var, aby uzyskać aktualną pierwszą odpowiedź.

Pierwszy z hierarchią widoku:

extension UIView {
    var previousFirstResponder: UIResponder? {
        return nextFirstResponder ?? subviews.compactMap { $0.previousFirstResponder }.first
    }
}

To będzie szukać pierwszej odpowiedzi wstecz, a gdyby nie mógł go znaleźć, powiedziałby jego podviewom, aby zrobiły to samo (ponieważ jego podview next niekoniecznie musi być sobą). Dzięki temu możemy go znaleźć z dowolnego widoku, w tym UIWindow.

I wreszcie możemy zbudować to:

extension UIResponder {
    static var first: UIResponder? {
        return UIApplication.shared.windows.compactMap({ $0.previousFirstResponder }).first
    }
}

Więc kiedy chcesz odzyskać pierwszego ratownika, możesz zadzwonić:

let firstResponder = UIResponder.first
 0
Author: yesleon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 16:51:30