반응형
LinkedIn 개발자로 성장하면서 남긴 발자취들을 확인하실 수 있습니다.
Github WWDC Student Challenge 및 Cherish, Tiramisul 등 개발한 앱들의 코드를 확인하실 수 있습니다.
개인 앱 : Cherish 내 마음을 들여다보는 시간, 체리시는 디자이너와 PM과 함께 진행 중인 1인 개발 프로젝트입니다.
10년 후, 20년 후 나는 어떤 스토리 텔러가 되어 있을지 궁금하다. 내가 만약에 아직 조금 더 탐구하고 싶은 게 있고, 궁금한 게 있다면, 그게 설사 지금 당장의 내 인생에 도움이 안 되는 것 같더라도 경험해보자. 그 경험들을 온전히 즐기며 내 것으로 만들고, 내 일에 녹여내고... 그러다보면 그 점들이 모여 나란 사람을 그려내는 선이 될 테니까.

Recent Posts
Recent Comments
Total
관리 메뉴

꿈꾸는리버리

[SwiftUI] Notification 구현하기 - x시간 후, 특정일자에, 특정 지역에서 본문

오뚝이 개발자/SwiftUI

[SwiftUI] Notification 구현하기 - x시간 후, 특정일자에, 특정 지역에서

rriver2 2024. 5. 1. 02:02
반응형

 

오늘은 iOS에서 local Notification를 띄우는 방법에 대한 공부를 했다.

그동안 어려울 거라고 생각하고 미루고만 있었는데, 해보니까 생각보다 안 어렵더라구요..?

 

조금은 허무한 감이 있어서 과거에 아무 것도 모르고 어려울 거라고 생각했던 제가 부끄러웠고, 역시... 안 해본 곳, 안 가본 곳은 더 크고 무섭게 느껴지는 것 같다...

다음번에는 server 통신이 필요한 Notification까지! 섭렵해보자구 ~~ ㅎㅎ



1️⃣ Notification 허용해주세요 구하기

import SwiftUI
import UserNotifications

class NotificationManager {
    static let instance = NotificationManager() // Singleton
    
    /// 제일 처음에 알림 설정을 하기 위한 함수 -> 앱이 열릴 때나 button 클릭시에 함수 호출 되도록!
    func requestAuthorization() {
        let options: UNAuthorizationOptions = [.alert, .sound, .badge]
        UNUserNotificationCenter.current().requestAuthorization(options: options) { suceess, error in
            if let error {
                print("ERROR: \(error)")
            } else {
                print("SUCCESS")
            }
        }
    }
}

 

UNAuthorizationOptions은 다음과 같은 종류가 있는데, .alert은 진짜 그 알림을 띄운다 이거고,, .sound는 띵! 소리 나는 거 !! 그리고 badge는 앱로고 위에 빨간 점으로 1,2,3 이렇게 숫자 쌓이는 녀석입니다. 나머지는 안 써봐서 잘 모르겠네요 근데 criticalAlert 궁금해서 소리 넣어봤는데 재밌었어 ㅋㅋㅋㅋㅋㅋ

2️⃣ 알림 설정을 위한 얇은 배경 지식

👉🏻 Notification Trigger 종류

Notification의 Trigger에는 다음 5개의 종류가 있는데, 나는 상단 3개에 대해 알아봤다. 

4번째는 쓸 일이 없을 거 같았고, 5번째 UNNotificationTrigger는 백그라운드 알림, 즉 서버통신으로 인한 알림을 의미하는 듯했다.

오늘은 local 알림이 목표였으니까!! 상단에 있는 3가지 녀석에 대해 해보려 한다.

 

👉🏻 UNMutableNotificationContent

이거는 알림이 울릴 때 설정할 수 있는 내용들이다. 

아래의 코드와 같이 코드를 보기만 해도 뭔지 알 것 같은... 설명은 생략하겠습니당...!

let content = UNMutableNotificationContent()
content.title = "title"
content.subtitle = "subtitle"
content.sound = .default
content.badge = 1

 

👉🏻 UNNotificationRequest

트리거를 만들고 나서 Notification을 생성할 수 있다.

이때 identifier는 해당 알림에 대한 id 값으로, 이 id 값을 통해 해당 알림을 찾아서 수정, 취소할 수 있다. ( 뒤에 코드로 다룰 예정 )

let triger = ~~ 각각 트리거 만들기

let request = UNNotificationRequest(
            identifier: UUID().uuidString,
            content: content,
            trigger: trigger)
        
UNUserNotificationCenter.current().add(request)

 

 

🌟 정리

private func requestScheduleNotification() {
        let content = UNMutableNotificationContent()
        content.title = "title"
        content.subtitle = "subtitle"
        content.sound = .default
        content.badge = 1
        
        // 아래 3️⃣의 trigger 제작 코드가 들어갈 부분
        
        let request = UNNotificationRequest(
            identifier: UUID().uuidString,
            content: content,
            trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
}

 

 

 

3️⃣ Trigger 제작 방법

🌟 UNCalendarNotificationTrigger

Notification Trigger 중에 젤 처음에 있는 녀석. 가장 활용도도 높고 자주 사용될 것 같은 Trigger이다.

다음주 토요일 3시에 알림
매주 수요일 4시에 알림
매달 첫째주 6시에 알림

 

이름 그대로 Calendar..! 특정 날짜에 알림을 설정할 때 사용된다.

 

아래 코드와 같이 Trigger를 만들 수 있고, repeats를 통해 반복할 건지, 말 건지를 설정할 수 있다.

DateCompoents의 경우에는 아래의 weekday, hour, minute 말고도 커스텀할 수 있는 여지가 많으니까, 이것저것 파라매터들을 봐놓으면 좋을 것 같다.

        var dateComponents = DateComponents()
        // weekday: 월1 화2 수3 목4 금5 토6 일7
        dateComponents.weekday = weekday
        dateComponents.hour = 18
        dateComponents.minute = 00
        
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)

 

🌟 UNTimeIntervalNotificationTrigger

지금을 기준으로 x초 후에 알림을 줄 수 있다. 아래의 코드는 30분 후에 알림을 주는 코드이다.

// Fire in 30 minutes (60 seconds times 30)
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: (30*60), repeats: false)

 

🌟 UNLocationNotificationTrigger

해당 지역에 왔을 때 알림을 줄 수 있는 코드이다. ( 사실 이게 제일 신기했다. )

위도, 경도에서 찍은 지점을 중심으로 100 만큼 떨어져 있을 때 알림이 가는 Trigger이다.

let coordinates = CLLocationCoordinate2D(
            latitude: 40.00, // 위도 
            longitude: 50.00)  // 경도
        
let region = CLCircularRegion(
            center: coordinates,
            radius: 100,
            identifier: UUID().uuidString)
            
region.notifyOnEntry = true // 설정한 지역 구간에 들어왔을 때
region.notifyOnExit = false // 설정한 지역 구간을 나갈 때
        
let trigger = UNLocationNotificationTrigger(region: region, repeats: true)

 

4️⃣ 마지막... 알림 제거 방법

- removeAllPendingNotificationRequests는 아직 울리지 않은 알림들 취소시키는 것!

- removeAllDeliveredNotifications 이게 뭔가 싶을 수 있는데, 내 예상으로 카톡 같은 경우에 앱이 열리면 모든 미리보기 카톡 알림이 사라지는 것처럼,, 현재 사용자 폰에 이미 떠 있는 모든 알림을 제거하는 것!

func cancelNotification() {
        // 곧 다가올 알림 지우기
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        // 현재 사용자 폰에 떠 있는 알림 지우기
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
}
    
/// badge 삭제하기
func deleteBadgeNumber() {
        UNUserNotificationCenter.current().setBadgeCount(0)
}

 

 

 

 

+) 미니미한 이슈...

앱 동의가 허용될 때 딱 한 번 매주 알림 설정을 하려고 하다보니까 아래와 같이 해당 알림이 있는지 확인해서 없으면 해당 알림 설정을 하도록 했다. userdefault로 관리할까? 싶기도 했는데 생각해보니까 user가 setting 앱에서 알림을 끄고 다시켰을 때처럼 예외 케이스가 있을 것 같아서 아래와 같이 구현했다.

/// 제일 처음 앱 열릴 때
    func viewAppear() {
        UNUserNotificationCenter.current()
            .getNotificationSettings { permission in
                switch permission.authorizationStatus  {
                case .notDetermined: // 제일 처음 알림 설정
                    self.requestAuthorization(date: Date(h: 18, mi: 0), text: "K_오늘 나의 하루는 어땠나요?")
                default:
                    break
                }
            }
    }
    
    /// 알림 설정 시 확인할 때
    func checkNotificationSetting(completion: @escaping (Bool) -> Void) {
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            switch settings.authorizationStatus {
            case .authorized:
                completion(true)
            default:
                completion(false)
            }
        }
    }

// -> View에서는 아래와 같이 사용
//NotificationManager.instance.checkNotificationSetting { isAuthorized in
//    if isAuthorized {
//        // 동의시
//    } else {
//        // 비동의시
// 		  NotificationManager.instance.openSettingApp()
//    }
//}
    
    /// 설정앱의 Cherish 앱 열기
    func openSettingApp() {
        guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
        
        if UIApplication.shared.canOpenURL(url) {
            DispatchQueue.main.async {
                UIApplication.shared.open(url)
            }
        }
    }

 

반응형
Comments