Local Notification

pcsoyeon·2021년 11월 17일
0

로컬 알림 생성

로컬 알림은 앱 내부에서 만든 특정 메시지를 iOS의 알림 센터를 통해 전달하는 방법을 말한다. (앱이 종료되어 있거나 백그라운드 상태일 때 앱에서의 정보를 전달할 수 있는 대표적인 방법 중 하나이다.)

로컬 알림의 목적

  1. 앱에 대한 환기
    로컬 알림은 iOS 스케줄러에 의해 발송되고 앱 내부에서 미리 메시지를 구성한 후 발송될 시각을 iOS 스케줄러에 등록하면 그 시각에 맞추어 자동으로 발송한다.
    -> 스케줄러에 의해 발송되므로 앱 실행 중이 아니더라도 메시지를 받을 수 있다. (+ 알림 센터에 표시된 메시지를 클릭해서 앱을 실행하고 원하는 기능/화면으로 이동 가능하다.)

로컬 알림의 경우 앱 실행 여부와 상관 없이 사용할 수 있으나 앱이 실행 중이라면 로컬 알림보다는 메시지 창을 이용하는 것이 더 확실하고 효율적이다. 로컬 알림은 사용자로부터 관심이 멀어지는 상황에서 앱에 대한 주의를 환기하는 목적으로 사용하는 것이 좋다.

(앱이 실행 중이 아닐 때 홍보 효과를 두기 위해 로컬 알림을 사용하므로 이에 대한 작업이 대부분 앱 델리게이트 클래스에서 이루어지고 있다.)

  1. 스케줄링
    사용자 개인의 일정을 관리할 수 있다. 사용자가 앱에 일정을 등록하고 이에 맞춰 일정 알림 메시지가 뜨는 기능과 같이 특정 시각에 무언가를 알려주는 용도로 사용한다. iOS 스케줄러에 등록하면 따로 관리하지 않아도 해당 시간에 알아서 메시지를 보내기 때문이다.

UserNotification

iOS 10 이후로 애플에서는 사용자 알림에 대한 모든 것을 전담할 UserNotification 프레임 워크를 새로 제공하기 시작했다.

그래서 iOS 10 버전 이상부터는 UserNotification 프레임 워크를, 이외에는 UILocalNotification객체를 사용해서 로컬 알림을 구현해야 한다.

UserNotification 프레임워크에서 눈여겨봐야 할 객체는 다음과 같다.

  • UNMutableNotificationContent
  • UNTimeIntervalNotificationTrigger
  • UNNotificationRequest
  • UNUserNotificationCenter

UNMutableNotificationContent

기본적인 속성을 담는 콘텐츠 역할
-> 앱의 title, sub title, content, banner, sound 등을 설정

해당 객체는 수정이 불가하며 객체로부터 속성을 읽어 들일 수만 있다. 그래서 기존에 등록된 알림 콘텐츠를 읽을 때에만 사용할 수 있고 속성을 따로 설정하기 위해서는 반드시 UNMutableNotificationContent 객체를 사용해야 한다.

UNTimeIntervalNotificationTrigger

알림 발송 조건을 관리
-> 로컬 알림 발생 시각과 반복 여부를 설정

iOS 10 이전에는 Date() 타입을 통해서 시각을 설정할 수 있었지만 이 객체를 이용하면 몇 분 후와 같은 시간 간격을 설정하여 메시지를 보낼 수 있다.
(입력 단위는 초, 하루 중 특정한 시각에 맞추어 전송하고 싶자면? UNCalendarNotificationTrigger 객체를 사용하면 된다.)

UNNotificationRequest

앞서 두가지 객체를 통해서 알림의 내용과 발생 조건을 설정 했다면, 이들을 모아서 UNNotificationRequest를 통해 알림 요청 객체가 생성된다.

UNUserNotificationCenter

실제 발송을 담당하는 센터

등록된 알림 내용을 확인하고 정해진 시각에 발송하는 역할을 한다. 싱글턴 방식으로 동작하기 때문에 따로 인스턴스를 생성하지 않고 current() 메소드를 통해서 참조 정보를 가져올 수 있다.

구현

사용자 권한 요청

먼저 앱의 로컬 알림을 받을 것인지 사용자의 권한을 요청 받아보자

    let notificationCenter = UNUserNotificationCenter.current()
    
    func userRequest() {
        let options: UNAuthorizationOptions = [.alert, .sound, .badge]
            
        notificationCenter.requestAuthorization(options: options) {
            (granted, error) in
            print("granted NotificationCenter : \(granted)")
        }
    }

위의 메소드를 application(_:didFinishLaunchingWithOptions:) 메소드에 추가한다. 이 메소드는 앱 델리게이트 안에 있는 것으로 앱이 처음 실행될 때 호출되는 메소드이다.
(앱에서 사용할 클래스와 리소스를 모두 메모리에 로드하고 아직 첫 화면을 디바이스에 띄우기 전에 호출 된다.)

UserNotification 프레임워크에서는 로컬 알림 또는 푸시 알림을 사용하기 위해 UNUserNotificationCenter 객체를 이용해서 미리 알림 설정 환경을 정의하고 사용자에게 승인 받는다.


위와 같은 메시지 창으로 알림 권한을 요청 받는다. 만약 여기서 Don't Allow를 선택하게 된다면 앱에서 알림을 발송하더라도 사용자는 받을 수 없다.

로컬 알림/푸시 알림에 대한 요청 시점을 대부분 앱의 최초 진입에서 받고 있지만 이것이 항상 옳다고 할 수 없다. (적절한 시점에 어떤 알림인지 충분하게 설명하는 내용으로 권한을 요청하는 것이 좋다.)

.requestAuthorization 메소드는 두가지 인자를 받고 있다.

  1. 첫번째 인자값은 알림 메시지에 포함될 내용들이다. 여러 항목을 한번에 입력할 수 있도록 배열 타입으로 되어 있다.
    (위에서는 알림창, 사운드, 배지 를 설정했고 이들은 UNAuthorizationOptions 열거형 객체에 정의되어 있는 값들이다.)
  2. 두번째 인자값은 클로저 형태로 받고 있다. 경우에 따라서 알림 설정에 동의했을 때 처리할 작업들이 있다. 서버 푸시의 경우 사용자가 동의한 경우, 디바이스 토큰 정보를 서버로 보내 저장해야 한다. (그래야 서버에서 해당 디바이스로 서버 푸시 메시지를 보낼 수 있다.)

내용 설정

    func generateNotification(){
        notificationCenter.getNotificationSettings { settings in
            if settings.authorizationStatus == .authorized {
                let content = UNMutableNotificationContent()
                
                content.title = "⚡️ SO KYTE ⚡️"
                content.body = "왜 사람은 일을 해야 하는걸까?\n노력 없이 성과를 바라면 안되는거야?"
                content.sound = UNNotificationSound.default
                content.badge = 1
                
                let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
                let identifier = "SO KYTE"
                let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
                
                self.notificationCenter.add(request) { (error) in
                    if let err = error {
                        print(err.localizedDescription)
                    }
                }
            } else {
                // 알림 동의하지 않은 경우
            }
            
        }
    }

알림 메시지를 보내기 위해서 가장 먼저 확인해야 하는 것은 사용자의 동의 여부이다. 이 값은 getNotificationSettings() 메소드를 통해 확인할 수 있다.

만약 사용자가 허용했다면 (= .authorizationStatus 속성값이 .authorized 라면) 로컬 알림을 생성해야 한다.

로컬 알림의 생성은 발송할 내용을 정의하는 1단계, 발송 조건을 정의하는 2단계, 알림 요청을 만드는 3단계, notification center에 요청을 등록하는 4단계로 구성되어 있다.

발송 내용 정의

let content = UNMutableNotificationContent()

content.title = "⚡️ SO KYTE ⚡️"
content.subtitle = "뭘 봐."
content.body = "왜 사람은 일을 해야 하는걸까?\n노력 없이 성과를 바라면 안되는거야?"
content.sound = UNNotificationSound.default
content.badge = 1

먼저 UNMutableNotificationContent 객체를 생성한다.

그리고 발송할 내용을 작성한다.
title, sub title, body를 작성하고 .sound 속성을 통해 알림이 도착했을 때 소리를 설정할 수 있다.

발송 조건 정의

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)

UserNotification 프레임워크는 알림 발송 시간을 설정할 수 있도록 크게 두가지 객체를 제공한다.

하나는 UNTimeIntervalNotificationTrigger이고 발송 시각과 반복 여부를 설정할 수 있다. 단위는 초이고 위에서는 3초 후 알림 메시지를 발송하고 반복은 하지 않는다.

만약 하루 중 특정 시간에 발송하고 싶다면 UNCalendarNotificationTrigger 객체를 사용하면 된다.

알림 요청 생성

let identifier = "SO KYTE"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)

위에서 설정한 내용과 조건과 함께 알림 요청 객체를 생성한다.
UNNotificationRequest 객체로 만들 수 있고 첫번째 인자값인 identifier는 해당 알림에 대한 임의의 식별 아이디를, 두번째 인자값인 content는 발송할 내용을, 세번째 인자값은 발송 시간 조건을 입력하면 된다.
-> 식별 아이디의 경우 여러 알림이 등록되었을 때 특정한 알림을 취소하고 싶을 때 사용할 수 있다.

notification center에 등록

self.notificationCenter.add(request) { (error) in
	if let err = error {
		print(err.localizedDescription)
        }
}

마지막으로 설정한 알림을 노티피케이션 센터에 추가하면 된다. 등록된 알람은 iOS 센터에 등록하고 정해진 시간에 발송될 것이다.

로컬 알림 처리

전달 받은 알림에 대해서 처리하는 방법을 알아보자.
사용자가 알림 메시지를 클릭해서 앱에 진입했을 때 상황에 따라 다른 액션을 취해야 한다. (e-commerce 서비스의 경우, 쿠폰 알림이 온다면 바로 쿠폰 모음 화면으로 이동하는 것이 더 자연스럽다.)

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    let notification = NotificationCenter.shared
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        notification.userRequest()
        notification.notificationCenter.delegate = self
        
        return true
    }
    
    ...
}

extension AppDelegate: UNUserNotificationCenterDelegate {
	// ...
}

이러한 분기 처리를 UNUserNotificationCenterDelegate를 통해 처리할 수 있다. 앱 델리게이크 클래스에 UNUserNotificationCenterDelegate 프로토콜을 추가하면 된다.

  1. 앱 실행 도중에 알림 메시지가 도착한 경우
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.list, .sound, .banner])
    }

실행 도중 처리해야 할 과정이 있다면 completionHandler() 메소드를 호출해야 한다. 이를 생략하면 앱 실행 도중에 알림 배너는 실행되지 않는다.

  1. 알림 메시지를 통해 특정 화면으로 이동하고 싶은 경우
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        
        guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
            return
        }
        
        let storyboard = UIStoryboard(name: "First", bundle: nil)
        
        if response.notification.request.identifier == "SO KYTE" {
            print("Hello SO KYTE Notification")
            
            if  let secondVC = storyboard.instantiateViewController(withIdentifier: "SecondVC") as? SecondVC,
                let navController = rootViewController as? UINavigationController{
                
                navController.pushViewController(secondVC, animated: true)
            }
            
        }
        completionHandler()
    }

이 메소드는 사용자가 알림 메시지를 클릭 했을 때 실행된다. 식별값을 통해 특정한 알림에 따른 처리 구현을 할 수 있다.

profile
Slowly But Surely

0개의 댓글