프로젝트/Tempus

Timer, UserNotifications을 활용한 시간 측정 및 푸시알림을 적용

코르피 2023. 8. 21. 16:56
반응형

 

구현 내용

Timer 객체가 설정한 시간마다 UserNotifications를 이용해 사용자에게 푸시알림을 보여주는 것

 

개발 내용

🛠️ 알림 등록 및 제거

import UserNotifications

func enrollNotification(_ date: Date) {
    let calendar = Calendar.current
    let dateComponents = calendar.dateComponents([.hour, .minute], from: date)

    let content = UNMutableNotificationContent()
    content.title = "알림"
    content.body = "Daily Timer"
    content.sound = UNNotificationSound.init(named: UNNotificationSoundName("ringTune.m4a"))

    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
    let request = UNNotificationRequest(identifier: UUID().description, content: content, trigger: trigger)

    UNUserNotificationCenter.current().add(request)
}

UserNotifications를 사용하기 위해선 우선 UserNotifications 의 import가 필요.

 

작동원리

  1. UNUserNotificationCenter의 싱글톤 객체에 UNNotificationReqeust를 add한다.
  2. UNNotificationRequest id, 알림내용, 작동트리거를 필요로 한다.
  3. 알림내용인 UNMutableNotificationContent는 title, body 등 원하는 알림의 내용을 구성한다
    1. UNNotificationContent 도 있으나 이는 직접 생성 불가하다. APNs를 사용할 때 만들어지는 Content이다.
  4. 작동 트리거는 Push, Location, TimeInterval, Calendar 4가지가 있다.
    1. Push: APNs를 받는 트리거로 직접적으로 생성하지 않는다.
    2. Location: 사용자의 기기의 위치에 알림을 울려주며 CoreLocation이 필요하다.
    3. TimeInterval: 일정 간격을 설정하고 간격 종료 시 알림을 울린다. 반복 설정이 가능하다.
    4. Calendar: dateComponents를 이용한 설정한 시각에 알림을 울려줄 수 있다.

 

코드설명

위 코드는 알림을 등록하는 예제이다.

  • Calendar 객체를 이용해 date로 dateComponents를 옵션을 설정하고 만든다.
  • 알림에 들어갈 title, body, sound등 UNMutableNotificationContent을 만들어준다.
  • dateComponents와 content를 이용해 request를 만들어 준다.
    • 이 때, id는 겹쳐서는 안된다. 겹친다면 이전의 요청이 무시된다.
  • UNUserNotificationCenter에 요청을 등록한다.

 

 

 

🛠️ 타이머 객체

func timerStart() {
    guard timer == nil else { return }

    let interval = 0.1
    timer = Timer(timeInterval: interval, repeats: true, block: { [weak self] timer in
        guard let self else { return }
        self.remainTime.flow(second: interval)

        if self.remainTime.totalSecond <= 0 {
            self.remainTime = Time(second: self.originModel.wasteTime)
        }
    })

    RunLoop.current.add(timer!, forMode: .common)
}

 

작동원리

  1. Timer 객체를 만들어 현재쓰레드(main)의 RunLoop에 추가한다.
    1. 이 때, 추가할 수 있는 모드는 common, default, tracking 3가지가 있다
      1. default: 대부분의 작업이 사용되는 기본적으로 사용되는 모드
      2. common: default, tracking, modal을 포함하는 모드
      3. tracking: 사용자의 컨트롤을 추적하는 모드
  2. Timer 객체는 원하는 생성자로 만든다.
    1. 이 코드는 시간간격과, 반복여부, 실행블록 생성자를 사용했다.

 

코드설명

위 코드는 0.1초마다 블록을 실행하는 코드다.

 

  • 타이머가 두개이상 존재하지 않도록 nil 체크를 해준다.
  • 블록 실행 간격은 0.1초로 설정한다.
  • 객체가 가지고 있는 remainTime을 계속해서 flow 하다가 0이하가 된다면 시간을 재설정 한다.
    • 다시 0.1초마다 remainTime을 줄이는 코드가 반복된다.
  • 현재 코드가 진행중인 쓰레드의 RunLoop에 timer를 추가한다.

 

1. TimeInterval 마다 알림을 울려주는 코드

2. Timer 객체를 이용해 코드를 반복시켜 뷰를 업데이트 하는 코드

 

위 두 코드를 합쳐 동시에 실행되도록 처리해 주었다.

 

Timer 객체를 이용해 0이하가 될 때마다 알림을 울려주게 하기 위해서는
앱을 백그라운드에서 실행시켜야 하는데 이는 배터리 수명관리에 좋지 않다.

 

또한 APNs를 사용하기에는 Apple 서버 상태에 따라 정확한 시점에 알림이 오지 않기 때문에 고려하지 않았다.

실행화면

 

Notification 실행화면

 

 

반응형