본문 바로가기

MOBILE/ios

[iOS] UserNotification으로 로컬 알림 사용하기

로컬 알림은 앱 내부의 메세지를 사용자에게 전달할 때 ios의 알림 센터를 거치도록 하여 전달하는 방식으로 이루어진다.

즉 앱이 종료되어 있거나 백그라운드 상태에서도 사용자 알림을 보낼 수 있다는 장점이 있다.

 

 

로컬 알림은 ios scheduler에 의해 발송된다. 앱 내부에서 미리 메세지를 구현하고, 이를 ios scheduler에 보내고자 하는 시각으로 등록해두면 자동으로 발송된다. 이때 scheduler에 등록된 이후로는 Ios가 모든 발송을 관리하기 때문에 앱 내부에서는 할 일이 없다.

따라서 로컬 알림의 대부분은 AppDelegate class에서 작업이 이루어진다. (life cycle method와 함께 쓰일 때가 많음)

ios 10 이상부터는 UserNotification 객체를 사용하고, 그 이하 버전에서는 UILocalNotification 객체를 사용해야 한다.


UserNotification

UserNotification은 사용자 알림을 처리하기 위한 알림 전용 프레임워크이다. 독립된 프레임워크이므로 import 문으로 반입이 필요하다.

이 프레임워크에서 중요한 객체는 다음 4가지이다.

 

- UNMutableNotificationContent

- UNTimeIntervalNotificationTrigger

- UNNotificationRequest

- UNUserNotificationCenter

 

UNMutableNotificationContent

알림에 필요한 메세지와 같은 기본적인 속성을 저장하는 contents이다. 

알림 메세지의 title, subtitle, message 등을 지정 가능하다. 

UNNotificationContent 는 같은 역할을 하지만 수정 불가능하다는 특징이 있다. 따라서 알림 컨텐츠를 읽기에만 적용된다.

 

UNTimeIntervalNotificationTrigger

알림 발송 조건을 관리한다. 이때 발생 조건이란 발생 시간, 반복 여부 이다. "몇분 후" 와 같은 시간 설정에 사용되며 이때 발생 시간의 입력값은 초 단위이다.

하루 중 특정 시간에 알림 메세지를 전송하고 싶은 경우에는 UNCalendarNotificationTrigger 객체를 사용할 수 있다.

 

UNNotificationRequest

알림 콘텐츠 객체와 발송 조건 객체를 인자값으로 하여 알림 요청 객체를 생성한다.

 

UNUserNotificationCenter

실제 알림 발송을 담당하는 센터이다.

이 객체는 singleton pattern이다. 즉 하나의 인스턴스만 실행되도록 보장된다.

따라서 객체를 새로 생성하는 것이 아니라 current() method를 통해서 참조해야 한다.

이렇게 가져온 참조 정보에 UNUserNotificationCenter:add(_:) method에 인자값으로 UNNotificationRequest 요청 객체를 전달하면 알림 등록이 완료된다.

 

UserNotification 객체는 알림을 사용하기 전에 사용자에게 승인을 받아야 한다. 이때 사용되는 method는 requestAuthorization() 이다. 예시를 보면서 확인해보자


requestAuthorization()

 

 

첫번째 파라미터, options

알림 메세지에 포함될 항목들이다. 이때 여러 항목이 포함될 수 있으므로 배열 타입으로 정의되어 있다.

 

두번째 파라미터, completionHandler

사용자가 메세지 창의 버튼을 눌렀을 때 실행될 클로저 구문이다.

이때  알림 여부 true/false 를 위한 Bool type, 오류 발생 시 사용하는 Error 두 가지이다.

 

developer document에 나와있는 문서를 보면 다음과 같다.

 

 

맨 처음에 알림 설정에 대한 사용자 승인을 받고, 이 정보는 system에 저장되어 매번 보이지 않아야 하는 것이 핵심이다.

이 정보는 getNotificationSettings() 메소드를 통해서 가져올 수 있다.

다음과 같은 형태로 사용한다.

 

let notiCenter = UNUserNotificationCenter.current()
notiCenter.getNotificationSettings(completionHandler: {settings in
	// handler code
})

앱이 실행되었을 때 사용자 승인을 받는 코드를 작성해보자.

이때 사용되는 life cycle method는 application(_:didFinishLaunchingWithOptions) 이다.

이 메소드는 모든 리로스와 클래스들이 메모리에 로드되고 [시작 화면 표시 ~ 첫 화면을 띄우기 전]에 호출된다.

 

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
        
    if #available(iOS 10.0, *) {
        let noti = UNUserNotificationCenter.current()
        noti.requestAuthorization(options: [.alert, .badge, .sound], completionHandler: {(didAllow, e) in})
    }
    
    return true
}

 

이때 UserNotification 객체는 ios 10.0 이상부터 지원하므로 available 구문으로 버전을 확인해야 한다.

결과는 다음과 같다.

첫번째 파라미터로 넘겨준 인자들이 alert의 메세지로 뜨게 된다.

 

결과

그렇다면 이렇게 승인되거나 승인되지 않았음을 구분해서 알람을 보낼지 말지 결정해야 한다.

이때 사용되는 것이 getNotificationSettings() 메소드라고 했다. 이를 사용해보자.

이때 앱이 background로 전환될 때 알림 센터에 등록하기 위해서 willresign 메소드에 구현하였다. (구현 시점은 의미 없음)

혹은 Scene 기반으로 작동하는 경우 sceneWillResignActive 에 등록하면 된다.

 

func applicationWillResignActive(_ application: UIApplication) {
    let noti = UNUserNotificationCenter.current()
    
    noti.getNotificationSettings(completionHandler: {settings in
        if settings.authorizationStatus == .authorized {
            // Allow 일때의 코드
        }
    })
}

또는

  func sceneWillResignActive(_ scene: UIScene) {
      let noti = UNUserNotificationCenter.current()
    
    noti.getNotificationSettings(completionHandler: {settings in
        if settings.authorizationStatus == .authorized {
            // Allow 일때의 코드
        }
    })
}

 

app life cycle 메소드는 다음 포스팅을 참고하면 좋다.

 

[iOS] iOS의 UIApplicationDelegate의 life cycle method

UIKit으로 ios 프로젝트를 만들면 AppDelegate.swift 파일을 자동으로 생성해준다. 파일을 열어보면 AppDelegate 클래스는 UIApplicationDelegate protocol을 구현하고 있음을 확인할 수 있다. 이 AppDelegate 클..

josushell.tistory.com


그렇다면 권한이 ok인 경우에 알람을 보내는 법을 알아보자.

 

이때 알림의 내용과 속성을 정하는 객체는 다음과 같다.

badge = 앱 위에 뜨는 새로 표시

title = main title

subtitle = subtitle

body = 알림 메세지

sound = 알림 소리

userInfo = 로컬 알림과 함께 전달하고 싶은 값이 있는 경우에 딕셔너리로 전달한다.

이 속성은 화면에는 표시되지 않지만 이 알람을 눌렀을 때 연결되는 app delegate 메소드에서는 참조 가능하다.

 

요청 객체의 속성은 다음과 같다.

 

 

identifier: 해당 알림에 대한 식별 아이디 (여러개의 알림이 있는 경우, 이를 구분하기 위함)

content: 발송할 내용

trigger: 발송 시각 조건

 

위에서 살펴본 객체들을 모두 활용해서 알림을 설정할 수 있다.

이 알림은 background 상태가 되고 5초 뒤에 noti 알림을 보낸다.

  func sceneWillResignActive(_ scene: UIScene) {
        let noti = UNUserNotificationCenter.current()
            
        noti.getNotificationSettings(completionHandler: {settings in
            if settings.authorizationStatus == .authorized {
                // Allow 일때의 코드
                
                // 알림 내용을 설정
                let notiContent = UNMutableNotificationContent()
                    
                notiContent.badge = 1
                notiContent.title = "noti title"
                notiContent.subtitle = "this is noti subtitle"
                notiContent.body = "welcome to josushell's tistory"
                notiContent.sound = .default
                notiContent.userInfo = ["date" : Date()]
                
                // 알림 발생 조건
                let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
                
                // 요청 객체
                let request = UNNotificationRequest(identifier: "wake", content: notiContent, trigger: trigger)
                    
                // 알림 센터에 등록
                noti.add(request)
            }
        })
    }

 

 

결과는 어떻게 나올 것인가? 다음과 같다.

 

 

이때 alarmTest 앱 위에 표시된 숫자 1이 바로 badge 속성이다.


알람을 보낸 경우 대부분 알람을 표시한게 다가 아닌 경우가 많다. 예를 들어, 알람을 클릭하면 앱으로 이어지게 한다거나

알람을 클릭하면 특정 링크로 이어지게 하는 경우가 대부분이다.

이런 알림을 처리할때 UserNotification 프레임워크에서는 델리게이트 패턴 을 사용한다. 다음번에는 이에 대해 알아보자.

 

 

[iOS] UNUserNotificationCenterDelegate 로 보낸 로컬 알람 처리하기

 

josushell.tistory.com