키보드가 표시되고 숨겨지는시기를 감지하는 방법


답변:


166

키보드에 대한 메시지를 수신하도록 설정된 클래스의 ViewDidLoad 메서드에서 :

// Listen for keyboard appearances and disappearances
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(keyboardDidShow:)
                                             name:UIKeyboardDidShowNotification
                                           object:nil];

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

그런 다음 지정한 메서드 (이 경우 keyboardDidShowkeyboardDidHide) 에서 이에 대해 수행 할 수 있습니다.

- (void)keyboardDidShow: (NSNotification *) notif{
    // Do something here
}

- (void)keyboardDidHide: (NSNotification *) notif{
    // Do something here
}

필드를 통해 탭하면 작동하지 않습니다. 이에 대한 해결책이 무엇이며 실제 iPad에서 탭을 통해 탭할 수 있는지 궁금하십니까?
i--

@apprentice 탭하면 키보드가 표시되지 않는다는 뜻입니까?
매튜 프레드릭

포커스가있는 필드 아래에 키보드로 가려진 필드가있는 경우 키보드가 위로 올라 오는 순간에만 알림이 전달되므로보기가 탭에 계속 유지됩니다.
i--

3
@apprentice 키보드가 언제 나타나는지 아는 것과는 다른 문제인 활성화되는 각 텍스트 필드에 따라 스크롤 뷰를 밀어서 수동으로 관리해야합니다. 뷰 컨트롤러를 UITextFieldDelegate로 만든 다음 textFieldShouldReturn:메서드 를 구현하십시오 . 당신은 얻을 것이다 textField당신이 당신의 자신의 텍스트 필드에 비교하고 스크롤 할 수 있습니다 인수로 입력 scrollView하므로 적절한에 textField가 표시되고 있음을.
매튜 프레드릭

94

addObserver에서 필요할 수 있습니다 viewDidLoad. 그러나 필요 addObserverviewWillAppearremoveObserverviewWillDisappear당신이 당신의보기를 변경하는 때 발생 방지 드문 충돌합니다.

스위프트 4.2

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear), name: UIResponder.keyboardWillShowNotification, object: nil)
}

@objc func keyboardWillAppear() {
    //Do something here
}

@objc func keyboardWillDisappear() {
    //Do something here
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

Swift 3 및 4

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: Notification.Name.UIKeyboardWillHide, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear), name: Notification.Name.UIKeyboardWillShow, object: nil)
}

@objc func keyboardWillAppear() {
    //Do something here
}

@objc func keyboardWillDisappear() {
    //Do something here
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

이전 Swift

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillAppear:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillDisappear:", name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWillAppear(notification: NSNotification){
    // Do something here
}

func keyboardWillDisappear(notification: NSNotification){
    // Do something here
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

9
viewWillDisappear ...에서 관찰자를 제거하는 경우 viewDidLoad 대신 viewWillAppear에 추가해야합니다.
FouZ

사실입니다. 자유롭게 답을 수정하세요. 나는 그것을 받아 들일 것
Esqarrouth

@FouZ는 다음 deinit과 같이 관찰자를 제거하는 것이 더 낫습니다 :deinit { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) }
Crashalot

Swift 3에서 위의 deinit 코드 블록은 다음과 같습니다.deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) }
Md. Najmul Hasan

@Crashalot deinit는 vc를 닫을 때까지 실행되지 않습니다. 따라서이 항목 위에 다른 vc를 표시하면 알림을 계속 수신합니다. 나는 목적 이이 vc가 표시되는 동안에만이 알림을 듣는 것이라고 생각하므로 viewdidappear에 추가하고 viewdiddissapear에서 제거하는 것이 더 나아 보입니다.
포치

19

스위프트 3 :

NotificationCenter.default.addObserver(self, selector: #selector(viewController.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(viewController.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

func keyboardWillShow(_ notification: NSNotification){
    // Do something here
}

func keyboardWillHide(_ notification: NSNotification){
    // Do something here
}

9

스위프트 4 :

  NotificationCenter.default.addObserver( self, selector: #selector(ControllerClassName.keyboardWillShow(_:)),
  name: Notification.Name.UIKeyboardWillShow,
  object: nil)
  NotificationCenter.default.addObserver(self, selector: #selector(ControllerClassName.keyboardWillHide(_:)),
  name: Notification.Name.UIKeyboardWillHide,
  object: nil)

다음으로, 객체의 수명이 끝날 때 알림 수신을 중지하는 메서드를 추가합니다.

Then add the promised methods from above to the view controller:
deinit {
  NotificationCenter.default.removeObserver(self)
}
func adjustKeyboardShow(_ open: Bool, notification: Notification) {
  let userInfo = notification.userInfo ?? [:]
  let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
  let height = (keyboardFrame.height + 20) * (open ? 1 : -1)
  scrollView.contentInset.bottom += height
  scrollView.scrollIndicatorInsets.bottom += height
}

@objc func keyboardWillShow(_ notification: Notification) {
  adjustKeyboardShow(true, notification: notification)
}
@objc func keyboardWillHide(_ notification: Notification) {
  adjustKeyboardShow(false, notification: notification)
}

+=인 세트가 더 크고 더 큰 얻을 수 있도록 나타납니다.
Wez

adjustKeyboardShow 함수는 매우 잘 만들어진 기능이라고 생각합니다. 감사합니다.
홍콩 개발자

Swift 5 알림 이름은 UIResponder.keyboardWillShowNotificationUIResponder.keyboardWillHideNotification이고 키보드 정보 키는 UIResponder.keyboardFrameBeginUserInfoKey입니다.
CodeBrew

5

스위프트-4

override func viewWillAppear(_ animated: Bool) {
   super.viewWillAppear(animated)
   addKeyBoardListener()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self) //remove observer
}

func addKeyBoardListener() {
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil);
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil);
}

@objc func keyboardWillShow(_ notification: Notification) {

}

@objc func keyboardWillHide(_ notification: Notification) {

}


4

2 가지 키보드 알림에 등록하고 싶을 것입니다.

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

TextField를 키보드로 조정하는 방법에 대한 훌륭한 게시물 -http : //iosdevelopertips.com/user-interface/adjust-textfield-hidden-by-keyboard.html


4

Swift 4.2에서는 알림 이름이 다른 네임 스페이스로 이동했습니다. 그래서 지금은

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    addKeyboardListeners()
}


override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}


func addKeyboardListeners() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
}

@objc private extension WhateverTheClassNameIs {

    func keyboardWillShow(_ notification: Notification) {
        // Do something here.
    }

    func keyboardWillHide(_ notification: Notification) {
        // Do something here.
    }
}

3

스위프트 5

위의 답변이 정확합니다. 을 마무리하는 도우미를 만들고 싶지만 notification's observers.

이점 :

  1. 키보드 동작을 처리 할 때마다 반복 할 필요가 없습니다.
  2. 다른 열거 형 값을 구현하여 다른 알림을 확장 할 수 있습니다.
  3. 여러 컨트롤러에서 키보드를 다루어야 할 때 유용합니다.

샘플 코드 :

extension KeyboardHelper {
    enum Animation {
        case keyboardWillShow
        case keyboardWillHide
    }

    typealias HandleBlock = (_ animation: Animation, _ keyboardFrame: CGRect, _ duration: TimeInterval) -> Void
}

final class KeyboardHelper {
    private let handleBlock: HandleBlock

    init(handleBlock: @escaping HandleBlock) {
        self.handleBlock = handleBlock
        setupNotification()
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    private func setupNotification() {
        _ = NotificationCenter.default
            .addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { [weak self] notification in
                self?.handle(animation: .keyboardWillShow, notification: notification)
            }

        _ = NotificationCenter.default
            .addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { [weak self] notification in
                self?.handle(animation: .keyboardWillHide, notification: notification)
            }
    }

    private func handle(animation: Animation, notification: Notification) {
        guard let userInfo = notification.userInfo,
            let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
            let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
        else { return }

        handleBlock(animation, keyboardFrame, duration)
    }
}

사용하는 방법:

private var keyboardHelper: KeyboardHelper?
...

override func viewDidLoad() {
   ...
   keyboardHelper = KeyboardHelper { [unowned self] animation, keyboardFrame, duration in
        switch animation {
        case .keyboardWillShow:
            print("keyboard will show")
        case .keyboardWillHide:
            print("keyboard will hide")
        }
    }

}


2

스위프트 4 -dd 20 october 2017

override func viewDidLoad() {
    [..]

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(_:)), name: Notification.Name.UIKeyboardWillHide, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(_:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
}

@objc func keyboardWillAppear(_ notification: NSNotification) {
    if let userInfo = notification.userInfo, 
       let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue).cgRectValue {
           let inset = keyboardFrame.height // if scrollView is not aligned to bottom of screen, subtract offset
           scrollView.contentInset.bottom = inset
           scrollView.scrollIndicatorInsets.bottom = inset
    }
}

@objc func keyboardWillDisappear(_ notification: NSNotification) {
    scrollView.contentInset.bottom = 0
    scrollView.scrollIndicatorInsets.bottom = 0
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

1

하나 이상의 UITextFields가 있고 키보드가 나타나거나 사라질 때 (또는 이전에) 무언가를해야하는 경우이 접근 방식을 구현할 수 있습니다.

UITextFieldDelegate수업에 추가 하십시오. 정수 카운터를 할당합니다.

NSInteger editCounter; 

이 카운터를 viewDidLoad. 그런 다음 메서드를 구현 textFieldShouldBeginEditing하고 textFieldShouldEndEditing위임합니다.

첫 번째에서 editCounter에 1을 추가하십시오. editCounter의 값이 1이되면 키보드가 나타납니다 (YES를 반환하는 경우). editCounter> 1이면 키보드가 이미 표시되고 다른 UITextField에 포커스가 있음을 의미합니다.

에서 textFieldShouldEndEditingeditCounter에서 빼기 1. 0이되면 키보드가 해제되고 그렇지 않으면 화면에 남아 있습니다.


0

KBKeyboardObserver 라이브러리를 사용할 수 있습니다 . 여기에는 몇 가지 예제가 포함되어 있으며 간단한 인터페이스를 제공합니다.



0

아, 이것이 진짜 답입니다.

import Combine


class MrEnvironmentObject {
    /// Bind into yr SwiftUI views
    @Published public var isKeyboardShowing: Bool = false

    /// Keep 'em from deallocatin'
    var subscribers: [AnyCancellable]? = nil

    /// Adds certain Combine subscribers that will handle updating the
    ///  `isKeyboardShowing` property 
    ///
    /// - Parameter host: the UIHostingController of your views. 
    func setupSubscribers<V: View>(
        host: inout UIHostingController<V>
    ) {
        subscribers = [
            NotificationCenter
                .default
                .publisher(for: UIResponder.keyboardWillShowNotification)
                .sink { [weak self] _ in
                    self?.isKeyboardShowing = true
                },
            NotificationCenter
                .default
                .publisher(for: UIResponder.keyboardWillHideNotification)
                .sink { [weak self, weak host] _ in
                    self?.isKeyboardShowing = false
                    // Hidden gem, ask me how I know:
                    UIAccessibility.post(
                        notification: .layoutChanged, 
                        argument: host
                    )
                },
            // ...
            Profit
                .sink { [weak self] profit in profit() },
        ]
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.