3.6 Notification : 메시지가 담긴 쪽지

Jay·2025년 2월 6일

Level 3 - SingleView App

목록 보기
6/24

Goal

포어그라운드로 전환되는 시점에 시간이 업데이트 될 수 있도록 구현해보기

Meterials

Structure Notification
노티피케이션센터에 등록된 모든 옵저버에게 발송되는 정보를 담은 컨테이너
Class NotificationCenter
등록된 옵저버에 노티피케이션을 발송하는 센터

func addObserver(_ observer: Any, selector aSelector: Selector, name
aName: NSNotification.Name?, object anObject: Any?)
: 노티피케이션을 받을 수 있도록 감시하는 옵저버를 추가한다.

func removeObserver(_ observer: Any)
: 추가한 옵저버를 삭제한다.

func post(_ notification: Notification)
: 받은 노티피케이션을 수신자에게 발송한다.

Thinking First

어떻게 하면 다음 코드가 포어그라운드로 전환될 때마다 실행이 되게 할 수 있을까?

 let formatter = DateFormatter()
 formatter.timeStyle = .medium
 timeLabel.text = formatter.string(from: clock.date)

우선 간편히 실행할 수 있도록 별도의 메서드(updateTime)로 선언해두자.
그렇다면 updateTime 메서드를
applicationWillEnterForeground() 내에서 바로 실행되도록 할 수 있을까?
가능하지만 서로 다른 객체에서 메서드를 호출하는 것은 그렇게 간단하지 않다.
지금 단계에서는 별로 좋은 방법은 아니므로 NotificationCenter를 이용해 보자.

post 메서드는 노티피케이션에 이름을 지어 센터에 발송한다. 우리는 포어그라운드로 전환되는 시점에 노티피케이션을 받아야 하므로 applicationWillEnterForeground() 내에 Post 메서드를 구현해놓으면 될 것이다.

addObserver메서드는 특정 객체를 받고자 하는 이름의 노티피케이션을 수신하는 옵저버로 노티피케이션센터에 등록할 수 있으며 수신하는 시점에 특정 메서드를 호출할 수 있는 기능이 있다.
뷰가 처음 로드되는 시점에 호출되는 viewDidLoad 메서드내에 뷰컨트롤러를 옵저버로 한번만 등록해 놓으면 뷰컨트롤러는 원하는 노티피케이션이 수신될 때마다 곧바로 updateTime 메서드를 호출할 수 있게 된다.

Making Next

//  ViewController.swift

class ViewController: UIViewController {
   @IBOutlet weak var timeLabel: UILabel!
   let clock = Clock()
  
   override func viewDidLoad() {
       super.viewDidLoad()
// viewDidLoad 메서드가 포어그라운드로 진입하는 시점보다 늦으므로 처음에 한번 실행되도록 호출한다.
       updateTimeLabel()

// 현재의 뷰컨트롤러를 옵저버로 등록하여 "fore" 라는 이름의 노티피케이션만 수신하고 그 시점에
// updateTime 메서드가 호출되도록 센터에 등록한다.
       NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateTimeLabel), name: NSNotification.Name("fore"), object: nil)
   }

   @objc func updateTimeLabel() {
       let formatter = DateFormatter()
       formatter.timeStyle = .medium
       timeLabel.text = formatter.string(from: clock.date)
   }
}



//  AppDelegate.swift
...
// 포어그라운드로 진입할 때마다  "fore" 라는 이름의 노티피케이션을 발송한다.
   func applicationWillEnterForeground(_ application: UIApplication) {
        let notificationName = Notification.Name("fore")
       NotificationCenter.default.post(Notification(name: notificationName))
   }
....

앱을 실해해보면 기대와 달리 시간이 업데이트 되지 않는데 그 이유는 포어그라운드로 진입할때마다 updateTimeLabel() 을 계속 실행하더라도 동일한 시간이 표시되기 때문이다.
다시 Clock 클래스로 돌아가서 date 를 보면 초기화 할때 한번 Date() 를 할당하고 나중에 date 에 접근하더라도 계속 동일한 인스턴스를 사용하기 때문에 동일한 시간이 표시된다.
다음과 같이 currentDate 라는 연산형 프로퍼티를 추가해서 비교해보자.
currentDate 는 접근시마다 Date()를 리턴하므로 계속 현재시간에 대한 새로운 인스턴스를 생성한다.

class Clock {
    let date = Date()
    
    var currentDate: Date {
        return Date()
    }
}

물론 updateTimeLabel() 도 다음과 같이 수정되어야 한다.


  @objc func updateTimeLabel() {
 ...
       timeLabel.text = formatter.string(from: clock.currentDate)
   }

Closing

정리하자면 뷰컨트롤러는 옵저버로서 “fore” 라는 이름의 노티피케이션이 센터로 날라오는지 눈을 부릅뜨고 지켜보는 감시자가 된다. 앱 델리게이트는 포어그라운드로 진입할 때마다 “fore” 노티피케이션을 센터에 발송하고 뷰컨트롤러는 그 시점에 “fore” 노티피케이션을 낚아채어 미리 구현해 놓은 메서드를 실행시킨다. 앱을 실행해보면 포어그라운드로 진입할 때마다 시간이 업데이트 되는 것을 볼 수 있다.

profile
Software Engineer Specialized on iOS

0개의 댓글