Swift) 유저에게 알림 보내기 (Local Notification)

L3C4Y4 velog·2024년 12월 4일
0

유저에게 알림을 보내는 방법 중 하나인 Local Notification에 대해 정리해보았습니다.

1. 알림 권한 요청하기

func requestAuthorization() {
    let options: UNAuthorizationOptions = [.alert, .badge, .sound]
    
    UNUserNotificationCenter.current().requestAuthorization(options: options) { granted, error in
        if granted {
            print("알림 권한을 허용했습니다")
        } else {
            print("알림 권한을 거부했습니다")
        }
        
        if let error {
            print(error.localizedDescription)
        }
    }
} 

알림 권한에 포함될 기능 설정인 UNAuthorizationOptions (링크)를 통해 다양한 옵션들을 선택할 수 있습니다.

2. 알림 Content 만들기

let content = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Hello, World. it's body"
content.sound = .default
content.badge = 1

badge 설정은 앱 아이콘에 표시되는 알림의 갯수를 나타내는 설정인데요.
badge를 1로 값을 설정해놨을 경우에는 알림이 올 때마다 1씩 추가되는 것이 아닌 알림이 몇 번을 오든 1로 고정시켜두는 것을 알아두시면 좋을 것 같습니다.

3. 알림 Trigger 만들기

알림 내용을 만들었다면, 이제 앱에게 알림을 언제 보낼지를 설정해주기 위해 Trigger를 만들어줘야 합니다.

1. 특정 시간에 알림 보내줘 (UNCalendarNotificationTrigger)

ex) 주말의 시작인 매주 토요일 아침에 기분 좋게 알림을 받고싶어

var dateComponents = DateComponents()

// 일요일부터 1, 월요일은 2, 화요일은 3 ~~~ 토요일은 6
dateComponents.weekday = 6
dateComponents.hour = 9
dateComponents.minute = 30

let trigger = UNCalendarNotificationTrigger(
    dateMatching: dateComponents, repeats: true
)

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

UNUserNotificationCenter.current().add(request) { error in
    if let error {
        print(error.localizedDescription)
    } else {
        print("알림 추가 완료")
    }
}

UNCalendarNotificationTriggerrepeats을 통해 알림을 반복할 것인지 설정할 수 있습니다.

2. 특정 시간 뒤에 알림을 보내줘 (UNTimeIntervalNotificationTrigger)

ex) 지금으로 부터 30초 뒤에 알림을 보내줘

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

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

UNUserNotificationCenter.current().add(request) { error in
    if let error {
        print(error.localizedDescription)
    } else {
        print("알림 추가 완료")
    }
}

3. 특정 위치에 도달하거나 떠날 때 알림을 보내줘 (UNLocationNotificationTrigger)

ex) 내가 지정한 목적지에 다와가면 알림을 보내줘

let center = CLLocationCoordinate2D(latitude: 35.222710, longitude: 128.582206)
let region = CLCircularRegion(
    center: center,
    radius: 100, // 반경 100미터
    identifier: UUID().uuidString
)
region.notifyOnEntry = true // 진입 시 알림
region.notifyOnExit = false // 떠날 때 알림

let trigger = UNLocationNotificationTrigger(
    region: region, repeats: false
)

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

UNUserNotificationCenter.current().add(request) { error in
    if let error {
        print(error.localizedDescription)
    } else {
        print("알림 추가 완료")
    }
}

4. 알림 삭제하기

알림을 삭제하는 두 가지 경우가 있는데요.

  • 유저에게 아직 보내지지 않은 알림을 삭제
  • 유저에게 전송되어서 알림 센터에 떠 있는 알림을 삭제

1. 유저에게 아직 보내지지 않은 알림 삭제하기

 // 보내지지 않은 알림 삭제하기
func removePendingNotifications(identifiers: [String]) {
    let center = UNUserNotificationCenter.current()
    
    // 보내지지 않은 모든 알림 삭제
    center.removeAllPendingNotificationRequests()
    
    // 보내지지 않은 알림 중 선택하여 삭제
    center.removePendingNotificationRequests(withIdentifiers: identifiers)
}

2. 이미 전송된 알림 삭제하기

카카오톡이나 인스타 DM 등 앱을 들어가면 알림 센터에 떠 있는 메시지 알림이 제거되는 경우라고 보시면 될 것 같습니다.

func removeDeliveredNotifications(identifiers: [String]) { // 이미 전송된 알림 삭제하기
    let center = UNUserNotificationCenter.current()
    
    // 전송된 알림 모두 삭제
    center.removeAllDeliveredNotifications()
    
    // 전송된 알림 중 선택하여 삭제
    center.removeDeliveredNotifications(withIdentifiers: identifiers)
}

5. 앱이 Foreground 상태일 때도 알림받기

@main
struct LocalNotificationApp: App {
    @UIApplicationDelegateAdaptor var appDelegate: AppDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        // 델리게이트 설정
        UNUserNotificationCenter.current().delegate = self
        return true
    }
}

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        // 알림 옵션 설정
        completionHandler([.badge, .banner])
    }
}

Foreground에서 받을 수 있는 알림 설정들

import Foundation
import UserNotifications
import CoreLocation

final class NotificationManager {
    static let instance = NotificationManager()
    
    func requestAuthorization() {
        let options: UNAuthorizationOptions = [.alert, .badge, .sound]
        
        UNUserNotificationCenter.current().requestAuthorization(options: options) { granted, error in
            if granted {
                print("알림 권한을 허용했습니다")
            } else {
                print("알림 권한을 거부했습니다")
            }
            
            if let error {
                print(error.localizedDescription)
            }
        }
    }
    
    func getAuthorizationStatus(completion: @escaping (UNAuthorizationStatus) -> Void ) {
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            completion(settings.authorizationStatus)
        }
    }
    
    func scheduleWithCalendar() { // 특정 시간에 알림 받기
        let content = UNMutableNotificationContent()
        content.title = "즐거운 토요일"
        content.body = "행복한 주말 되세요!"
        content.sound = .default
        
        var dateComponents = DateComponents()
        
        // 일요일부터 1, 월요일은 2, 화요일은 3 ~~~ 토요일은 6
        dateComponents.weekday = 6
        dateComponents.hour = 9
        dateComponents.minute = 30
        
        let trigger = UNCalendarNotificationTrigger(
            dateMatching: dateComponents, repeats: true
        )
        
        let request = UNNotificationRequest(
            identifier: UUID().uuidString, content: content, trigger: trigger
        )
        
        UNUserNotificationCenter.current().add(request) { error in
            if let error {
                print(error.localizedDescription)
            } else {
                print("알림 추가 완료")
            }
        }
    }
    
    func scheduleWithTimeInterval() { // 지금으로 부터 특정 시간 뒤 알림 받기
        let content = UNMutableNotificationContent()
        
        content.title = "안녕하세요"
        content.subtitle = "Foreground에서도 알림은 받으셔야죠"
        content.sound = .default
        
        let trigger = UNTimeIntervalNotificationTrigger(
            timeInterval: 1, repeats: false
        )
        
        let request = UNNotificationRequest(
            identifier: UUID().uuidString, content: content, trigger: trigger
        )
        
        UNUserNotificationCenter.current().add(request) { error in
            if let error {
                print(error.localizedDescription)
            } else {
                print("알림 추가 완료")
            }
        }
    }
    
    
    func scheduleWithLocation() { // 특정 위치에 도달하거나 떠날 때 알림 받기
        let content = UNMutableNotificationContent()
        content.title = "위치 알림"
        content.subtitle = "목적지까지 얼마 남지 않았어요"
        content.sound = .default
        
        let center = CLLocationCoordinate2D(latitude: 35.222710, longitude: 128.582206)
        let region = CLCircularRegion(
            center: center,
            radius: 100, // 반경 100미터
            identifier: UUID().uuidString
        )
        region.notifyOnEntry = true // 진입 시 알림
        region.notifyOnExit = false // 떠날 때 알림
        
        let trigger = UNLocationNotificationTrigger(
            region: region, repeats: false
        )
        
        let request = UNNotificationRequest(
            identifier: UUID().uuidString,
            content: content,
            trigger: trigger
        )
        
        UNUserNotificationCenter.current().add(request) { error in
            if let error {
                print(error.localizedDescription)
            } else {
                print("알림 추가 완료")
            }
        }
    }
    
    func removePendingNotifications(identifiers: [String]) { // 보내지지 않은 알림 삭제하기
        let center = UNUserNotificationCenter.current()
        
        // 보내지지 않은 모든 알림 삭제
        center.removeAllPendingNotificationRequests()
        
        // 보내지지 않은 알림 중 선택하여 삭제
        center.removePendingNotificationRequests(withIdentifiers: identifiers)
    }
    
    func removeDeliveredNotifications(identifiers: [String]) { // 이미 전송된 알림 삭제하기
        let center = UNUserNotificationCenter.current()
        
        // 전송된 알림 모두 삭제
        center.removeAllDeliveredNotifications()
        
        // 전송된 알림 중 선택하여 삭제
        center.removeDeliveredNotifications(withIdentifiers: identifiers)
    }
}

전체 코드 Github

profile
iOS 관련 정보들을 정리해두었습니다.

0개의 댓글