Communication over long distances with NotificationCenter

10375 단어 iOSiOS

What is notification center and how does it work?

The probelm of protocol-delegate pattern

  • protocol-delegate 패턴은 어떤 뷰 컨트롤러과 가까이 있는 다른 뷰 컨트롤러 사이에서 커뮤니케이션을 할 때는 효과적이다.
  • 그러나 멀리 있는 뷰 컨트롤러로 커뮤니케이션을 하려고 한다면, 출발하는 뷰 컨트롤러와 도착하는 뷰 컨트롤러 사이에 있는 모든 뷰 컨트롤러에 delegate를 정의해주어야 한다.

Notification Center (= Observer Pattern)

  • Notification center를 이용하면 위와 같은 문제를 해결할 수 있다.
  • Notification center는 어떤 뷰 컨트롤러가 broadcast message를 보낸다.

그러면 notificaton center를 이용해서 로그아웃 기능을 구현해보자.

Adding the logout button

일단 로그아웃을 위한 버튼을 만들자.

Hooking up Notification Center

*protocol-delegate 패턴을 사용해서 로그아웃 기능을 구현하려면 AccountSummaryViewController → MainViewController → AppDelegate 로 가는 모든 과정에서 delegate를 추가해주어야 한다.

  1. Util 폴더에 NSNotificationName.swift 파일을 생성한다.

    import Foundation
    
    extension Notification.Name {
        static let logout = Notification.Name("Logout")
    }

    Notification.Name 은 라디오 스테이션과 같은 역할을 해준다.

  2. AppDelegate에 이벤트를 등록한다.

    		private func registerForNotifications() {
            NotificationCenter.default.addObserver(self, selector: #selector(didLogout), name: .logout, object: nil)
        }
    • default: NotificationCenter의 싱글턴 인스턴스
  3. AccountSummaryViewControllerlogoutTapped 메소드에서 notification을 보내는 코드를 추가한다.

    extension AccountSummaryViewController {
        @objc func logoutTapped(sender: UIButton) {
            NotificationCenter.default.post(name: .logout, object: nil)
        }
    }

When not to use

🤔 protocol-delegate 패턴을 쓰지 말고 전부 Notification Center만 쓸 순 없는 걸까?

  • 앱의 많은 부분에서 notification center를 사용하면 코드를 이해하기 어려워진다.
  • 이벤트를 추적하기가 어려워진다.
  • 이벤트들의 조합이 의도하지 않은 결과를 만들 수 있다.

protocol-delegate는 뷰 컨트롤러와 뷰 컨트롤러, 또는 앱의 다른 부분과 직접적으로 커뮤니케이션 할 수 있는 방법이기 때문에 이를 더 많이 선호한다.

Notification Center를 과도하게 사용하지 않도록 주의하자.

Showing the password

로그인 화면에서 비밀번호 text field 우측에 있는 👁 아이콘을 누르면 비밀번호를 표시하거나 가릴 수 있는 기능을 구현해보자.
  1. Utils 폴더에서 UITextField+SecureToggle.swift 파일을 새로 만든다.

  2. 아래와 같이 코드를 작성한다.

    import Foundation
    import UIKit
    
    let passwordToggleButton = UIButton(type: .custom)
    
    extension UITextField {
        func enablePasswordToggle() {
            passwordToggleButton.setImage(UIImage(systemName: "eye.fill"), for: .normal)
            passwordToggleButton.setImage(UIImage(systemName: "eye.slash.fill"), for: .selected)
            passwordToggleButton.addTarget(self, action: #selector(togglePasswordView), for: .touchUpInside)
            rightView = passwordToggleButton
            rightViewMode = .always
        }
        
        @objc func togglePasswordView(_ sender: Any) {
            isSecureTextEntry.toggle()
            passwordToggleButton.isSelected.toggle()
        }
    }
    • 👁 버튼을 위한 passwordToggleButton 을 선언한다.
    • rightView, rightViewMode : 텍스트 필드의 우측에 👁 버튼이 보여지도록 하기 위한 설정
    • toggle() : Bool 값을 반전시키는 스위프트 메소드
    • 이 코드들은 UITextField의 extension 내에 있는 코드들이기 때문에 isSecureTextEntry 와 같은 프로퍼티들에 바로 접근할 수 있다.
  3. LoginView 에서 enablePasswordToggle() 을 적용시킨다.

    passwordTextField.enablePasswordToggle()

How to dynamically adjusting the font to fit the view

화면 크기가 작으면 label의 내용이 잘려서 나올 때가 있다. (iOS에서는 기본적으로 다 보여지지 않는 텍스트는 ... 로 표시해준다.)

실제 앱을 개발할 때 이런 문제가 발생하는 경우, 이를 해결하는 방법에는 세 가지가 있다.

  1. 화면 크기가 작은 디바이스는 지원하지 않는다고 명시하기
  2. 글자가 잘리는 것보다 모든 디바이스에서 폰트 크기를 통일하는 것에 중점 두기
  3. 폰트 크기를 동적으로 조절하기 → label이 view에서 가지는 너비를 기준으로

세 번째 방법은 adjustsFontSizeToFitWidth 프로퍼티를 이용해서 쉽게 적용할 수 있다.

// AccountSummaryCell.swift

nameLabel.adjustsFontSizeToFitWidth = true
balanceLabel.adjustsFontSizeToFitWidth = true

좋은 웹페이지 즐겨찾기