지난 포스팅에서는 UNUserNotification 객체를 사용하여 로컬 알람을 보내는 방법을 알아보았다.
로컬 알림은 잘 활용하면 사용자에게 아주 좋은 효과를 줄 수 있다는 점에서 유용하다.
하지만 로컬 알림이 알림에서 그치지 않고 사용자 액션으로 이어질 수 있도록 하기 위해서는 어떻게 해야할까?
예를 들면, 카카오톡은 상단바 알림에서도 메세지를 보낼 수 있다. 또는 알림을 터치하면 그 카카오톡방으로 들어가게 된다.
이러한 사용자 액션은 델리게이트 패턴을 이용하며, UNUserNotificationCenterDelegate 을 구현함으로써 만들 수 있다.
이러한 UNUserNotificationCenterDelegate의 메소드들을 살펴보자
Delegate 객체 설정하기
앞에서 말했듯이 UNUserNotificationCenterDelegate 은 델리게이트 패턴으로 동작한다.
즉 이벤트를 받았을 때 이를 전달해줄 delegate 객체가 필요하다는 의미이다. delegate 객체는 이 이벤트를 받아 특정 코드를 실행한다.
UNUserNotificationCenterDelegate를 구현하는 클래스에서 delegate 속성을 self 로 설정해주면 된다.
지난 포스팅에서는 앱 화면이 뜨자마자 user에게 알람 권한을 요청하는 코드를 작성했다.
그렇다면 user가 승인한 경우에 UNUserNotificationDelegate 의 delegate 객체는 이때 설정해야 하는 것이다.
따라서 지난 포스팅에서의 코드를 이어서 UIApplication 클래스에 UNUserNotificationDelegate를 구현한다.
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate
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
noti.delegate = self
})
}
return true
}
UNUserNotificationDelegate method
userNotificationCenter(_:didReceive:withCompletionHandler:)
앱의 실행 유무와 상관없이, 사용자가 실제로 알람을 클릭하면 실행된다.
optional func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void)
Parameters
center
notification을 받는 notification center 객체이다.
response
notification에 대한 user의 응답이 전달된다. 이 객체는 notification 정보와 사용자가 선택한 action에 대한 identifier를 포함한다. 카카오톡 처럼 textual response가 가능하도록 되어있다면, 이 객체 대신에 UNTextInputNotificationResponse 객체가 전달된다.
completionHandler
user의 응답에 대한 작업이 끝났을 때 실행되는 블록이다. 이 핸들러는 system에게 user action에 대한 처리가 끝났음을 알려주는 역할을 하기 때문에 반드시 호출해야 한다. 하지 않는 경우에는 custom action에 대한 작업이 실행되지 않는다.
Discussion
이 메소드는 synchronous한 code에서 호출 가능하다. asynchronous 하게 작동하기 위해서는 다음 코드를 사용할 수 있다.
optional func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async
userNotificationCenter(_:willPresent:withCompletionHandler:)
이 메소드는 앱 실행 중에도 메세지가 도착했는지 알 수 있다. 반대로 이를 구현하지 않으면 앱 실행 도중에 도착한 알림은 배너 형태로 표시되지 않는다.
optional func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
Parameters
center
notification을 받는 notification center 객체이다.
notification
전달되고자 하는 알림이다. 이 객체 안의 정보를 사용하여 action을 정한다.
completionHandler
알람에 대한 선택 사항과 함께 실행한다. 이 handler를 통해 system에게 어떻게 알람을 보낼지 알려주게 된다.
options
사용자에게 알람을 보낼때 사용하는 option이다. UNNotificationPresentationOptions 구조체에 정의되어 있다.
이 구조체의 속성은 다음과 같다.
실제로 사용자가 알림을 클릭했을 때 정보를 출력하도록 해보자.
이 경우 didReceive 메소드를 구현하면 된다.
알람을 다음과 같이 앱이 종료되고 난 후 5초 뒤에 보내지도록 했다고 가정한다.
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
print("sceneWillResignActive")
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)
print("등록 완료")
noti.add(request)
}
})
}
이 경우 이에 대한 반응 코드는 다음과 같다.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if (response.notification.request.identifier == "wake") {
print(response.notification.request.content.userInfo["date"]!)
}
completionHandler()
}
알림 정보에서 userInfo 속성에서 읽고 싶은 값을 정의하면 된다.
이때 notification.request.identifier는 알림 요청 객체를 생성할 때 정의한 식별자이다.
결과는 다음과 같다.
'MOBILE > ios' 카테고리의 다른 글
[iOS] RxSwift와 Observable, operator (0) | 2022.04.18 |
---|---|
[iOS] side bar 라이브러리 없이 직접 구현하기 (0) | 2022.04.11 |
[iOS] UserNotification으로 로컬 알림 사용하기 (0) | 2022.04.06 |
[swift] Property Wrapper: what does @ mean in swift? (0) | 2022.04.02 |
[iOS] URLSession을 사용하여 POST method 통신하기 (0) | 2022.04.01 |