카테고리 없음

[Swift - UIKit] 키보드 사용시 뷰 올리기, NotificationCenter

분홍이귀여워 2024. 11. 8. 14:54
반응형

키보드가 올라갈때 뷰를 가리게 되는 경우가 있다. 나의 경우 테이블뷰가 가려졌고 키보드가 올라갈때 테이블뷰도 y축으로 이동시키고 싶었다. 이 경우 NotificationCenter 를 이용해 키보드가 올라갔는지 내려갔는지를 보고받고 그에따라 키보드의 높이만큼 뷰를 올리거나 내려주면 불편함 없이 키보드를 사용할 수 있다.

 

1. 테이블뷰의 하단 제약조건을 변수에 저장하기

   lazy var tableViewBottomAnchorConstraint = tableView.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: 0)
   
   func setupConstraints() {
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 0),
            tableView.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 0),
            tableView.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor, constant: 0),
            tableViewBottomAnchorConstraint
        ])
    }

 

2. NotificationCenter 이벤트 등록

func setupKeyboardNotifications(showSelector: Selector, hideSelector: Selector) {
    //키보드가 올라갈때 관찰후 알림
    NotificationCenter.default.addObserver(self, selector: showSelector, name: UIResponder.keyboardWillShowNotification, object: nil)
    //키보드가 내려갈때 관찰후 알림
    NotificationCenter.default.addObserver(self, selector: hideSelector, name: UIResponder.keyboardWillHideNotification, object: nil)
}

addObserver -> 특정 이벤트가 발생할때 알림을 받겠다.
selector -> 알람이 발생했을때 실행할 메서드의 이름
name -> 어떤 종류의 알림을 수신할지
object -> 알림을 발송한 특정 객체를 지정할 수 있으며, nil이면 모든 객체로부터의 알림을 수신
여기서 name, 알림이름은 여러 종류가 있으며 키보드 관련 대표적인 것은 아래와 같다.
나는 키보드가 화면에 나타날때와 사라지기 직전을 선택했다.

 

  • UIResponder.keyboardWillShowNotification: 키보드가 화면에 나타날 때 발송
  • UIResponder.keyboardDidShowNotification: 키보드가 완전히 화면에 나타난 후에 발송
  • UIResponder.keyboardWillHideNotification: 키보드가 화면에서 사라지기 직전에 발송
  • UIResponder.keyboardDidHideNotification: 키보드가 완전히 사라진 후에 발송
  • UIResponder.keyboardWillChangeFrameNotification: 키보드의 프레임이 변경되기 직전에 발송 (예: 회전할 때).
  • UIResponder.keyboardDidChangeFrameNotification: 키보드의 프레임이 변경된 후에 발송

 

 

3. 함수 정의

//노티피케이션 셋팅
func setupNotification() {
    setupKeyboardNotifications(showSelector: #selector(moveUpAction), hideSelector: #selector(moveDownAction))
}
    
@objc func moveUpAction(notification: NSNotification) {
   adjustForKeyboard(notification: notification, bottomConstraint: todayTodoview.tableViewBottomAnchorConstraint)
}
    
@objc func moveDownAction() {
    resetAfterKeyboardDismiss(bottomConstraint: todayTodoview.tableViewBottomAnchorConstraint)
}

 

3-1. 키보드가 올라갔을때

키보드가 올라갈때는 adjustForKeyboard 함수를 통해 키보드의 높이를 구하여 테이블뷰의 하단 제약조건  constant: 0 에서 키보드 높이만큼 - 해준다. 반대로 키보드가 내려갈때는 제약조건 - 에서 0으로 돌려준다.

    //키보드 올라갈때 실행하는 함수 -> 키보드 높이를 구해서 테이블뷰 하단 제약조건 변경
    func adjustForKeyboard(notification: NSNotification, bottomConstraint: NSLayoutConstraint) {
        //키보드 높이 구하기
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue) {
            let keyboardHeight = keyboardSize.cgRectValue.height
            
            if bottomConstraint.constant == 0 { //테이블뷰 하단 제약조건 키보드 높이만큼 -
                bottomConstraint.constant -= keyboardHeight
            }
        }
    }

 

3-2. 키보드가 내려갔을때

//키보드 내려갈때 실행하는 함수 -> 테이블뷰 위치 제자리로 돌리기
func resetAfterKeyboardDismiss(tableView: UITableView, bottomConstraint: NSLayoutConstraint) {
    if bottomConstraint.constant != 0 {
        bottomConstraint.constant = 0
    }
}


4. 이벤트 해제

화면이 종료되어 더이상 알림이 필요하지 않을경우 메모리 누수 방지를 위해 옵저버를 해제한다

func removeKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
deinit {
    removeKeyboardNotifications()
}

 

 

코드 전체보기

나는 여러개의 뷰컨트롤러에서 사용하기 위해 확장을 이용했다.

import UIKit

extension UIViewController {
    //이벤트 등록
    func setupKeyboardNotifications(showSelector: Selector, hideSelector: Selector) {
        //키보드가 올라갈때 관찰후 알림
        NotificationCenter.default.addObserver(self, selector: showSelector, name: UIResponder.keyboardWillShowNotification, object: nil)
        //키보드가 내려갈때 관찰후 알림
        NotificationCenter.default.addObserver(self, selector: hideSelector, name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    //키보드 올라갈때 실행하는 함수 - 키보드 높이를 구해서 테이블뷰 하단 제약조건 변경
    func adjustForKeyboard(notification: NSNotification, bottomConstraint: NSLayoutConstraint) {
        //키보드 높이 구하기
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue) {
            let keyboardHeight = keyboardSize.cgRectValue.height
            
            if bottomConstraint.constant == 0 { //테이블뷰 하단 제약조건 키보드 높이만큼 -
                bottomConstraint.constant -= keyboardHeight
            }
        }
    }
    
    //키보드 내려갈때 실행하는 함수 - 테이블뷰 위치 제자리로 돌리기
    func resetAfterKeyboardDismiss(bottomConstraint: NSLayoutConstraint) {
        if bottomConstraint.constant != 0 {
            bottomConstraint.constant = 0
        }
    }
    
    //이벤트 해제
    func removeKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    }
}

 

UIViewController

import UIKit

class YourViewController: UIViewController {

	override func viewDidLoad() {
        super.viewDidLoad()
        setupNotification()
    }
    
    //노티피케이션 셋팅
    func setupNotification() {
        setupKeyboardNotifications(showSelector: #selector(moveUpAction), hideSelector: #selector(moveDownAction))
    }
    
    @objc func moveUpAction(notification: NSNotification) {
        adjustForKeyboard(notification: notification, bottomConstraint: todayTodoview.tableViewBottomAnchorConstraint)
    }
    
    @objc func moveDownAction() {
        resetAfterKeyboardDismiss(bottomConstraint: todayTodoview.tableViewBottomAnchorConstraint)
        
    deinit {
        removeKeyboardNotifications()
    }

}

 

반응형