[iOS] Local Notification

RudinP·2023년 11월 9일
0

Study

목록 보기
115/227

Local Notification

예시: 캘린더 앱에서 알림 설정

iOS에서

  • 유저 노티피케이션 센터를 통해 로컬 노티피케이션 관리
  • 앱에서 노티피케이션을 예약하면 해당 시점에서 노티피케이션을 전달
  • 앱이 실행 중인 상태라면 앱으로 전달하고 실행 중이 아니라면 배너를 통해 노티피케이션 표시
  • 액션을 통해서 앱을 실행하지 않고도 간단한 작업을 수행 가능

구현

  1. 로컬 노티피케이션 권한 요청
  • 사용자가 직접 추가한 경우에만 로컬 노티피케이션 예약 및 수신 가능
  1. 노티피케이션 객체 생성 및 필요한 정보를 담아 노티피케이션 센터의 예약 요청
  2. 노티피케이션 전달됐을 때 실행 코드 구현
  • 로컬 노티피케이션은 실행 상태에 따라서 처리 방식이 달라짐.
    • foreground: delegate 메소드 호출
    • background or 실행중이 아닐 때: ios가 직접 노티피케이션 표시, 사용자가 배너를 터치하면 메소드 호출

프레임워크

UNUserNotificationCenter 클래스에 구현

  • 이 클래스의 인스턴스를 직접 생성하는 것은 불가
  • 항상 current() 메소드가 리턴하는 싱글톤 인스턴스를 이용

앱으로 전달 된 로컬 노티피케이션 처리

UNUserNOtificationCenterDelegate 프로토콜을 통해 처리

실제 구현

Appdelegate에서 구현

import UserNotifications를 해야함

alert: 배너를 통해 메시지 출력
badge: 앱 아이콘에 알림뱃지 표시
sound: 알림 소리 설정
여기서는 세 옵션을 모두 전달.

두번째 파라미터는 사용자가 허가 여부를 선택한 후 호출할 클로저 전달.
클로저에는 허가 여부와 오류 정보가 파라미터로 전달됨.

보통 사용자가 허용한 경우에 델리게이트를 설정하고 나머지 초기화 작업을 구현.
여기에서는 우선 델리게이트만 설정

구동 화면


허용 한 뒤, 다시 실행하면 해당 경고창은 뜨지 않는다.
대신, 클로저는 반복적으로 호출된다.(콘솔을 보면 granted true 출력)

노티피케이션과 관련된 작업은 항상 클로저에 전달되는 파라미터를 기준으로 구현해야함.
사용자의 허용을 캐시에 저장하고 저장된 값을 재사용하는것은 잘못된 방식.
항상 현재 설정값을 기준으로 구현해야 함.

지금까지의 코드는 최소의 구현 코드.
리모트 노티피케이션도 동일

버튼을 누를 시 Local Notification 예약

UNMutableNotificationContent 생성

InputField를 채우고 Picker View를 선택한 뒤, Schedule 버튼을 누르면 Local Notification을 설정하도록 구현

sound가 설정되어있다고 무조건 소리가 들리는 것이 아니라, 사운드 재생이 허용되어있어야 함.

UNTimeIntervalNotificationTrigger 생성

이어서 트리거를 통해 로컬 노티피케이션이 전달되는 조건 지정.
현재는 총 3개.

UNCalendarNotificationTrigger : 전달되는 날짜와 시간을 직접 지정할 때 사용
UNTimeIntervalNotificationTrigger: 현재 시간을 기점으로 지정
UNLocationNotificationTrigger: 특정 지역에서 전달해야 한다면

  • 특정 매장에 가면 노티피케이션을 통해 프로모션 정보 제공 구현 가능 여기서는 UNTimeIntervalNotificationTrigger 인스턴스를 생성하여 피커뷰에서 설정한 타임 인터벌 설정
  • repeats를 true로 하면 반복해서 전달됨. 이 경우에는 반드시 60보다 큰 interval을 전달해야 함. 이보다 작은 값을 전달하면 crash 발생

UNNotificationRequest 인스턴스 생성

identifier: 예약된 로컬노티피케이션을 삭제할때 사용하는 문자열. 여러 노티피케이션 사용 경우 직관적으로 설정하는 것이 중요
content: 앞에서 설정
trigger: 앞에서 설정

마지막으로 실제 예약을 요청해야 함

UNNotification 예약 설정


첫번째 파라미터: 리퀘스트 인스턴스 전달
두번째 파라미터: 예약 결과를 처리하는 클로저 전달. 오류가 있는 경우 콘솔에 출력

실행 화면

앱을 계속 실행중이면 알림이 뜨지 않고, 앱을 닫았을 때만 알림, 배지, 배너가 뜬다.

  • 앱을 실행중이지 않거나 백그라운드 실행: iOS가 직접 노티피케이션 표시
  • 앱이 포어그라운드에서 실행되면 delegate가 실행.

앱이 포어그라운드일때 노티피케이션 처리 구현

Appdelegate에서 처리


포어그라운드에서 실행 중일 때 로컬노티피케이션이 전달되면 이 메소드 호출
두 번째 파라미터를 통해 노티피케이션 객체 전달
리퀘스트 속성을 통해 로컬 노티피케이션을 요청할 때 전달한 컨텐트와 트리거 인스턴스에 접근 가능

메소드에서 필요한 기능을 구현한 다음, 반드시 세번째 파라미터인 컴플리션 핸들러를 호출하고, 노티피케이션 호출 방식을 지정해야 한다.

참고로 alert는 iOS 14.0부터 안쓰게 되었고, 대신 bannerlist를 사용해야 한다.

banner

  • foreground
    • 상단에 배너로 알림이 옴.
    • 알림 센터에 쌓이지 않음(잠금화면)
  • background
    • 상단에 배너로 알림이 옴.
    • 알림 센터에 쌓임.

list

  • foreground
    • 상단에 배너로 알림이 오지 않음.
    • 알림 센터에 쌓임.
  • background
    • foreground와 동일


이제 앱이 포어그라운드일때도 알림이 뜬다.

사용자가 배너를 터치 시 실행하는 메소드

(동일하게 Appdelegate)

  • 노티피케이션에 대한 정보는 두번째 파라미터에서 확인 가능

이전 메소드와 마찬가지로 필요한 코드를 구현한 다음, 세번째 파라미터인 컴플리션 핸들러를 호출해야 함.

배지를 초기화 하는 코드

앱에 표시되는 배지의 숫자는 노티피케이션 컨텐트에서 구현되어 있음.
하지만 초기화 하는 코드는 직접 구현해야 함
앱을 열 시 초기화 되도록 구현

UIApplication.shared를 통해 앱을 나타내는 싱글톤 인스턴스에 접근 가능

17.0 부터 안쓴다네요...말한대로 수정

  • 보통은 이렇게 바로 0으로 만드는 것이 아니라, 실제 확인한 수만큼 반영하는 것이 바람직함

결과

  • 백그라운드 뱃지 표시
  • 앱 다시 실행 시 뱃지 없어짐 확인
    (viewDidLoad에서 했기 때문에 아예 앱을 종료하고 다시 켜야 작동)
profile
곰을 좋아합니다. <a href = "https://github.com/RudinP">github</a>

0개의 댓글