【问题标题】:How can I programmatically check whether a keyboard is present in iOS app?如何以编程方式检查 iOS 应用程序中是否存在键盘?
【发布时间】:2010-12-02 05:05:30
【问题描述】:

我需要检查我的 iOS 应用中键盘可见性的情况。

伪代码:

if(keyboardIsPresentOnWindow) {
    //Do action 1
}
else if (keyboardIsNotPresentOnWindow) {
    //Do action 2
}

如何检查这种情况?

【问题讨论】:

标签: ios objective-c keyboard


【解决方案1】:

我认为您需要使用提供的有关键盘的通知:

发件人:http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITextField_Class/Reference/UITextField.html

键盘通知

当系统显示或隐藏 键盘,它发布了几个键盘 通知。这些通知 包含有关的信息 键盘,包括它的大小,其中 您可以用于计算 涉及移动视图。注册 这些通知是唯一的方法 获取某些类型的信息 键盘。该系统提供 以下通知 键盘相关事件:

* UIKeyboardWillShowNotification
* UIKeyboardDidShowNotification
* UIKeyboardWillHideNotification
* UIKeyboardDidHideNotification

有关这些的更多信息 通知,查看他们的描述 在 UIWindow 类参考中。为了 有关如何显示和隐藏的信息 键盘,请参阅文本和网页。

【讨论】:

  • 我查看了这些通知,但不知道如何查看这些通知。如果您可以发布一些示例,那将非常有帮助。
  • 看看 NSNotificationCenter。您必须注册您感兴趣的通知。不要忘记在您的应用程序退出时取消注册。
【解决方案2】:

当您知道键盘不可见时创建一个UIKeyboardListener,例如通过从applicationDidFinishLaunching 调用[UIKeyboardListener shared]

@implementation UIKeyboardListener

+ (UIKeyboardListener) shared {
    static UIKeyboardListener sListener;    
    if ( nil == sListener ) sListener = [[UIKeyboardListener alloc] init];

    return sListener;
}

-(id) init {
    self = [super init];

    if ( self ) {
        NSNotificationCenter        *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(noticeShowKeyboard:) name:UIKeyboardDidShowNotification object:nil];
        [center addObserver:self selector:@selector(noticeHideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
    }

    return self;
}

-(void) noticeShowKeyboard:(NSNotification *)inNotification {
    _visible = true;
}

-(void) noticeHideKeyboard:(NSNotification *)inNotification {
    _visible = false;
}

-(BOOL) isVisible {
    return _visible;
}

@end

【讨论】:

  • 注意:您可以使用 +(void)load 在此侦听器类上调用 init ,以便它通常作为拖放到任何项目中并从第二个应用程序启动时初始化,而不是您拥有记得在任何地方初始化它。
【解决方案3】:

drawnonward 的代码非常接近,但与 UIKit 的命名空间冲突,并且可以更容易使用。

@interface KeyboardStateListener : NSObject {
    BOOL _isVisible;
}
+ (KeyboardStateListener *)sharedInstance;
@property (nonatomic, readonly, getter=isVisible) BOOL visible;
@end

static KeyboardStateListener *sharedInstance;

@implementation KeyboardStateListener

+ (KeyboardStateListener *)sharedInstance
{
    return sharedInstance;
}

+ (void)load
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    sharedInstance = [[self alloc] init];
    [pool release];
}

- (BOOL)isVisible
{
    return _isVisible;
}

- (void)didShow
{
    _isVisible = YES;
}

- (void)didHide
{
    _isVisible = NO;
}

- (id)init
{
    if ((self = [super init])) {
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(didShow) name:UIKeyboardDidShowNotification object:nil];
        [center addObserver:self selector:@selector(didHide) name:UIKeyboardWillHideNotification object:nil];
    }
    return self;
}

@end

【讨论】:

  • 为什么需要自己的池?
  • +load 是 Objective-C 运行时调用的特殊方法。在应用程序二进制文件加载之后,但在输入 main() 函数之前,每个类都会调用它。无法保证自动释放池将处于活动状态。
  • MattDiPasquale:如果+load方法被删除,sharedInstance将永远不会被初始化。由于无法保证在运行时调用 +load 方法时自动释放池处于活动状态,因此有必要包装对系统提供的类的所有调用,以防它们调用自动释放。
  • 不错的答案!我知道这已经有几年的历史了,但是 NSAutoreleasePool alloc/release 现在可以替换为 @autoreleasepool { } 中的代码
  • 别忘了移除 Observer,可能在 KeyboardStateListener 的 dealloc 中。
【解决方案4】:

我想这可能对你有帮助,

+(BOOL)isKeyBoardInDisplay  {

    BOOL isExists = NO;
    for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows])   {
        if ([[keyboardWindow description] hasPrefix:@"<UITextEffectsWindow"] == YES) {
            isExists = YES;
        }  
    }

    return isExists;
}

谢谢,

纳文山

【讨论】:

  • 在iOS 6上,只有作品还没有出现!一旦他们的键盘显示一次,它就会停止工作。
【解决方案5】:

…或者采取简单的方法:

当您输入一个文本字段时,它会成为第一响应者,并出现键盘。 您可以使用[myTextField isFirstResponder] 检查键盘的状态。如果它返回YES,则键盘处于活动状态。

【讨论】:

  • 很好的解决方案,但是如果使用硬件键盘,这将不起作用(在 iPad 上并不罕见)。
  • 这不能回答问题。这会告诉您文本字段是否是第一响应者。我有一个带有多个子视图控制器的视图控制器,所有子视图控制器都包含 UITextFields。使用这种方法,我无法从我的父视图控制器判断键盘是否显示。唯一可靠的方法是使用其他答案中解释的通知方法
【解决方案6】:

试试这个功能

BOOL UIKeyboardIsVisible(){

BOOL keyboardVisible=NO;
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
    if (![[testWindow class] isEqual:[UIWindow class]]) {
        keyboardWindow = testWindow;
        break;
    }
}
// Locate UIKeyboard.
for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
    // iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
    if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) {
        keyboardVisible=YES;
    }
    if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) {
        keyboardVisible=YES;
        break;
    }
}
return keyboardVisible;

}

来自:iOS: How to access the `UIKeyboard`?

【讨论】:

    【解决方案7】:

    现在在 iOS8 中,这个解决方案当然行不通。 它最初是为 IOS4/5 编写的。

    试试这个解决方案:

    - (BOOL) isKeyboardOnScreen 
    {
        BOOL isKeyboardShown = NO;
    
        NSArray *windows = [UIApplication sharedApplication].windows;
        if (windows.count > 1) {
            NSArray *wSubviews =  [windows[1]  subviews];
            if (wSubviews.count) {
                CGRect keyboardFrame = [wSubviews[0] frame];
                CGRect screenFrame = [windows[1] frame];
                if (keyboardFrame.origin.y+keyboardFrame.size.height == screenFrame.size.height) {
                    isKeyboardShown = YES;
                }
            }
        }
    
        return isKeyboardShown;
    }
    

    【讨论】:

    • 假设多个窗口意味着一个键盘并且键盘总是第二个元素是无效的。
    • @jmah 当然这不是通用的方法,但它涵盖了大量的应用案例。任何尝试获取有关键盘信息的尝试都使用一些特定的视图层次结构,因为 Apple 没有为这种情况提供任何有用的 API。
    • 这不起作用,对我有用的是遍历所有视图,并为所有 UITextFields 或 UITextView 检查它们是否是第一响应者...如果其中任何一个返回 true 键盘是可见的,否则它不是
    【解决方案8】:

    一些观察:

    单例对象的推荐模式如下。 dispatch_once 确保类以线程安全的方式初始化一次,并且静态变量在外部不可见。而且它是标准的 GCD,所以不需要了解 Objective-C 的底层细节。

    + (KeyboardStateListener *)sharedInstance
    {
        static KeyboardStateListener* shared;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            shared = [[KeyboardStateListener alloc] init];
            // Other initialisations
        });
    
        return shared;
    }
    

    通常您不想只知道键盘是否可见,而是要知道它有多大。键盘并非都具有相同的尺寸。 iPhone 键盘比 iPad 键盘小。因此,您需要另一个属性 @property (readonly, nonatomic) CGRect keyboardRect;,它在 noticeShowKeyboard: 方法中设置,如下所示:

    NSValue* value = notification.userInfo [UIKeyboardFrameEndUserInfoKey];
    _keyboardRect = value.CGRectValue;
    

    重要的是要注意矩形在 UIWindow 坐标中并且不考虑屏幕旋转。所以调用者会通过调用来转换那个矩形

    KeyboardStateListener* listener = [KeyboardStateListener sharedInstance];
    CGRect windowRect = listener.keyboardRect;
    CGRect viewRect = [myView convertRect:windowRect fromView:self.window];
    

    如果用户在键盘可见时旋转屏幕,应用程序将被告知键盘已隐藏,然后再次显示。显示时,其他视图很可能尚未旋转。因此,如果您自己观察键盘隐藏/显示事件,请在实际需要时转换坐标,而不是在通知中。

    如果用户拆分或取消固定键盘,或使用硬件键盘,通知将始终将键盘显示为隐藏。取消停靠或合并键盘将发送“显示键盘”通知。

    监听器必须在键盘隐藏时初始化,否则会错过第一个通知,当键盘不隐藏时会认为键盘是隐藏的。

    所以知道你真正想要什么是非常重要的。此代码可用于将东西移出键盘(使用拆分或未停靠的键盘,这是用户的责任)。它不会告诉您用户是否可以在屏幕上看到键盘(在拆分键盘的情况下)。它不会告诉您用户是否可以键入(例如,当有硬件键盘时)。如果应用程序自己创建其他窗口,则查看其他窗口不起作用。

    【讨论】:

    • 关于 iPad 键盘的好警告,谢谢!
    【解决方案9】:

    BOOL isTxtOpen = [txtfieldObjct isFirstReponder]。如果返回 YES,则键盘处于活动状态。

    【讨论】:

      【解决方案10】:

      这是来自 Apple 在此处发布的 iOS 文本编程指南:https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

      基本上在您的 ViewDidLoad 中调用“registerForKeyBoardNotifications”。然后每次键盘激活时,都会调用“keyboardWasShown”。并且每次键盘消失时,都会调用“keyboardWillBeHidden”。

      // Call this method somewhere in your view controller setup code.
      - (void)registerForKeyboardNotifications {
          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
      }
      
      // Called when the UIKeyboardDidShowNotification is sent.
      - (void)keyboardWasShown:(NSNotification*)aNotification {
          NSLog(@"Keyboard is active.");
          NSDictionary* info = [aNotification userInfo];
          CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
      
          UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
          scrollView.contentInset = contentInsets;
          scrollView.scrollIndicatorInsets = contentInsets;
      
          // If active text field is hidden by keyboard, scroll it so it's visible
          // Your app might not need or want this behavior.
          CGRect aRect = self.view.frame;
          aRect.size.height -= kbSize.height;
          if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
              [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
          }
      }
      
      // Called when the UIKeyboardWillHideNotification is sent
      - (void)keyboardWillBeHidden:(NSNotification*)aNotification {
          NSLog(@"Keyboard is hidden");
          UIEdgeInsets contentInsets = UIEdgeInsetsZero;
          scrollView.contentInset = contentInsets;
          scrollView.scrollIndicatorInsets = contentInsets;
      }
      

      【讨论】:

        【解决方案11】:

        使用窗口子视图层次结构作为键盘显示的指示是一种 hack。如果 Apple 改变他们的底层实现,所有这些答案都会被打破。

        正确的方法是在应用程序范围内监视键盘显示和隐藏通知,例如在您的 App Delegate 内部:

        在 AppDelegate.h 中:

        @interface AppDelegate : UIResponder <UIApplicationDelegate>
        
        @property (assign, nonatomic) BOOL keyboardIsShowing;
        
        @end
        

        在 AppDelegate.m 中:

        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
        {
        
            // Monitor keyboard status application wide
            self.keyboardIsShowing = NO;
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification object:nil];
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                                     name:UIKeyboardWillHideNotification object:nil];
        
            return YES;
        }
        
        - (void)keyboardWillShow:(NSNotification*)aNotification
        {
            self.keyboardIsShowing = YES;
        }
        
        - (void)keyboardWillBeHidden:(NSNotification*)aNotification
        {
            self.keyboardIsShowing = NO;
        }
        

        然后你可以检查使用:

        BOOL keyboardIsShowing = ((AppDelegate*)[UIApplication sharedApplication].delegate).keyboardIsShowing;
        

        请注意,当用户使用蓝牙或外接键盘时,键盘显示/隐藏通知不会触发。

        【讨论】:

          【解决方案12】:

          下面是如何在 Swift 中做到这一点:

           func registerForKeyboardNotifications() {
              NSNotificationCenter.defaultCenter().addObserver(
                  self,
                  selector: "keyboardWasShown:",
                  name: UIKeyboardDidShowNotification,
                  object: nil)
          
              NSNotificationCenter.defaultCenter().addObserver(
                  self,
                  selector: "keyboardWillBeHidden:",
                  name: UIKeyboardWillHideNotification,
                  object: nil)
          }
          
          func keyboardWasShown(notification: NSNotification) {
              println("Keyboard was shown");
          }
          
          func keyboardWillBeHidden(notification: NSNotification) {
              println("Keyboard was dismissed");
          }
          

          别忘了注销:

           override func viewWillDisappear(animated: Bool) {
              NSNotificationCenter.defaultCenter().removeObserver(self,
                  name: UIKeyboardDidShowNotification,
                  object: nil)
          
              NSNotificationCenter.defaultCenter().removeObserver(self,
                  name: UIKeyboardWillHideNotification,
                  object: nil)
          }
          

          如果您想在按下“返回”按钮时关闭键盘:

          class ViewController: UIViewController, UITextFieldDelegate {
          
          @IBOutlet weak var yourTextField: UITextField!
          
          override func viewDidLoad() {
              super.viewDidLoad()
              registerForKeyboardNotifications()
              yourTextField.delegate = self
          }
          
          func textFieldShouldReturn(textField: UITextField!) -> Bool {
              self.view.endEditing(true);
              return false;
          }
          
          }
          

          【讨论】:

            【解决方案13】:

            要检查天气键盘是否出现,我们可以使用键盘预定义的通知。

            UIKeyboardDidShowNotification ,UIKeyboardDidHideNotification

            例如我可以使用下面的代码来监听键盘通知

            // 监听键盘出现和消失

            [[NSNotificationCenter defaultCenter] addObserver:self 
                                                     selector:@selector(keyboardDidShow:)
                                                         name:UIKeyboardDidShowNotification
                                                       object:nil];
            
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardDidHide:)
                                                         name:UIKeyboardDidHideNotification
                                                       object:nil];
            

            在我可以得到通知的方法中

            - (void)keyboardDidShow: (NSNotification *) notifyKeyBoardShow{
                // key board is closed
            }
            
            - (void)keyboardDidHide: (NSNotification *) notifyKeyBoardHide{
                // key board is opened
            }
            

            【讨论】:

              【解决方案14】:

              Swift 实现:

              class KeyboardStateListener: NSObject
              {
                static var shared = KeyboardStateListener()
                var isVisible = false
              
                func start() {
                  let nc = NSNotificationCenter.defaultCenter()
                  nc.addObserver(self, selector: #selector(didShow), name: UIKeyboardDidShowNotification, object: nil)
                  nc.addObserver(self, selector: #selector(didHide), name: UIKeyboardDidHideNotification, object: nil)
                }
              
                func didShow()
                {
                  isVisible = true
                }
              
                func didHide()
                {
                  isVisible = false
                } 
              }
              

              因为 swift 在启动时不执行类 load 方法,所以在应用启动时启动此服务很重要:

              func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
              {
                ...    
                KeyboardStateListener.shared.start() 
              }
              

              【讨论】:

              • 使用iOS 13,swift 5.0这最后一点,类加载似乎没有必要?
              【解决方案15】:

              Swift 3 实现

                  import Foundation
              class KeyboardStateListener: NSObject
              {
                  static let shared = KeyboardStateListener()
                  var isVisible = false
              
                  func start() {
                      NotificationCenter.default.addObserver(self, selector: #selector(didShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
                      NotificationCenter.default.addObserver(self, selector: #selector(didHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
                  }
              
                  func didShow()
                  {
                      isVisible = true
                  }
              
                  func didHide()
                  {
                      isVisible = false
                  } 
              }
              

              【讨论】:

              • 我建议删除 deinit 中的观察者,或者如果它在视图中的视图控制器将消失
              • 如果这是一个单例,那么使用 deinit 是没有意义的,因为它永远不会被 deinited
              【解决方案16】:

              这是我的解决方案,它将所有内容封装到一个静态方法中,您可以在任何地方调用它来检查:

              +(BOOL)isKeyboardVisible{
                  static id tokenKeyboardWillShow = nil;
                  static id tokenKeyboardWillHide = nil;
                  static BOOL isKbVisible = NO;
                  @synchronized (self) {
                      if (tokenKeyboardWillShow == nil){
                          tokenKeyboardWillShow = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                              @synchronized (self) {
                                  isKbVisible = YES;
                              }
                          }];
                      }
              
                      if (tokenKeyboardWillHide == nil){
                          tokenKeyboardWillHide = [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                              @synchronized (self) {
                                  isKbVisible = NO;
                              }
                          }];
                      }
                  }
              
                  return isKbVisible;
              }
              

              【讨论】:

                【解决方案17】:

                您可以迭代地检查父视图的子视图中的所有文本视图、文本字段和标签,以查看是否有类似以下内容的第一响应者:

                -(BOOL)isKeyboardActiveInView:(UIView *)view {
                    for (UIView *anyView in [view subviews]) {
                        if ([anyView isKindOfClass:[UITextField class]]) {
                            if (((UITextField *)anyView).isFirstResponder) {
                                return YES;
                            }
                        } else if ([anyView isKindOfClass:[UILabel class]]) {
                            if (((UILabel *)anyView).isFirstResponder) {
                                return YES;
                            }
                        } else if ([anyView isKindOfClass:[UITextView class]]) {
                            if (((UITextView *)anyView).isFirstResponder) {
                                return YES;
                            }
                        } else {
                            if ([self isKeyboardActiveInView:anyView]) {
                                return YES;
                            }
                        }
                    }
                    return NO;
                }
                

                【讨论】:

                • 如果你有子视图控制器会失败
                【解决方案18】:

                添加扩展程序

                extension UIApplication {
                    /// Checks if view hierarchy of application contains `UIRemoteKeyboardWindow` if it does, keyboard is presented
                    var isKeyboardPresented: Bool {
                        if let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow"),
                            self.windows.contains(where: { $0.isKind(of: keyboardWindowClass) }) {
                            return true
                        } else {
                            return false
                        }
                    }
                }
                

                然后检查键盘是否存在,

                if UIApplication.shared.isKeyboardPresented {
                     print("Keyboard presented")
                } else { 
                     print("Keyboard is not presented")
                }
                

                【讨论】:

                • 可以guard let keyboardWindowClass = NSClassFromString("UIRemoteKeyboardWindow") else { return false }; return UIApplication.shared.windows.contains(where: { $0.isKind(of: keyboardWindowClass) })
                • 当应用程序具有社交登录(如 facebook、google)时始终返回 true
                【解决方案19】:

                斯威夫特 4

                extension UIViewController {
                    func registerKeyboardNotifications() {
                        let center = NotificationCenter.default
                        center.addObserver(self, selector: #selector(keyboardWillBeShown(note:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
                        center.addObserver(self, selector: #selector(keyboardWillBeHidden(note:)), name: Notification.Name.UIKeyboardWillHide, object: nil)
                    }
                
                    func removeKeyboardNotifications() {
                        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
                        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
                
                    }
                
                    @objc
                    func keyboardWillBeShown(note: Notification) {}
                
                    @objc
                    func keyboardWillBeHidden(note: Notification) {}
                
                }
                
                final class MyViewController: UIViewController {
                
                    // MARK: - Properties
                    var isKeyboardVisible = false
                
                    // MARK: - Life Cycle
                    override func viewWillAppear(_ animated: Bool) {
                        super.viewWillAppear(animated)
                        registerKeyboardNotifications()
                    }
                
                    override func viewWillDisappear(_ animated: Bool) {
                        super.viewWillDisappear(animated)
                        removeKeyboardNotifications()
                    }
                
                    // MARK: - Keyboard Handling
                    override func keyboardWillBeShown(note: Notification) {
                        isKeyboardVisible = true
                        let userInfo = note.userInfo
                        let keyboardFrame = userInfo?[UIKeyboardFrameEndUserInfoKey] as! CGRect
                        let contentInset = UIEdgeInsetsMake(0.0, 0.0, keyboardFrame.height, 0.0)
                        tableView.contentInset = contentInset
                    }
                
                   override func keyboardWillBeHidden(note: Notification) {
                        tableView.contentInset = .zero
                        isKeyboardVisible = false
                   }
                
                   // MARK: - Test
                   fileprivate func test() {
                        if isKeyboardVisible { // do something
                        }
                   }
                }
                

                【讨论】:

                • 对我来说效果很好(Xcode 10.2,Swift4)只是好奇为什么没有人赞成这个?
                • 不,如果之前的视图控制器已经提供了键盘,这将不起作用。
                • 理想情况下不应该出现前一个控制器提供键盘的情况,因为响应者不会出现在新控制器中,它将被关闭。
                【解决方案20】:

                SWIFT 4.2 / SWIFT 5

                class Listener {
                   public static let shared = Listener()
                   var isVisible = false
                
                   // Start this listener if you want to present the toast above the keyboard.
                   public func startKeyboardListener() {
                      NotificationCenter.default.addObserver(self, selector: #selector(didShow), name: UIResponder.keyboardWillShowNotification, object: nil)
                      NotificationCenter.default.addObserver(self, selector: #selector(didHide), name: UIResponder.keyboardWillHideNotification, object: nil)
                   }
                
                   @objc func didShow() {
                     isVisible = true
                   }
                
                    @objc func didHide(){
                       isVisible = false
                    }
                }
                

                【讨论】:

                  【解决方案21】:

                  SwiftUI - 完整示例

                  import SwiftUI
                  
                  struct ContentView: View {
                      
                      @State private var text = defaultText
                      
                      @State private var isKeyboardShowing = false
                      
                      private static let defaultText = "write something..."
                      
                      private var gesture = TapGesture().onEnded({_ in
                          UIApplication.shared.endEditing(true)
                      })
                      
                      var body: some View {
                          
                          ZStack {
                              Color.black
                              
                              VStack(alignment: .leading) {
                                  TextField("placeholder", text: $text)
                                      .foregroundColor(.white)
                                      .padding()
                                      .background(Color.green)
                              }
                              
                              .padding()
                          }
                          .edgesIgnoringSafeArea(.all)
                          .onChange(of: isKeyboardShowing, perform: { (isShowing) in
                              if isShowing {
                                  if text == Self.defaultText { text = "" }
                              } else {
                                  if text == "" { text = Self.defaultText }
                              }
                          })
                          .simultaneousGesture(gesture)
                          .onReceive(NotificationCenter.default
                                      .publisher(for: UIResponder.keyboardWillShowNotification), perform: { (value) in
                                          isKeyboardShowing = true
                                      })
                          .onReceive(NotificationCenter.default
                                      .publisher(for: UIResponder.keyboardWillHideNotification), perform: { (value) in
                                          isKeyboardShowing = false
                                      })
                      }
                  }
                  
                  extension UIApplication {
                      func endEditing(_ force: Bool) {
                          self.windows
                              .filter{$0.isKeyWindow}
                              .first?
                              .endEditing(force)
                      }
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2015-07-24
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-11
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多