나의 발자취

[SwiftUI] Notification 기능 구현하기 본문

앱 개발/iOS

[SwiftUI] Notification 기능 구현하기

달모드 2024. 11. 21. 15:30

지난 포스팅

2024.11.21 - [앱 개발/iOS] - [UIKit] Notification 기능 구현하기

 

[UIKit] Notification 기능 구현하기

이번에는 UIKit을 이용해서 Noti를 만들어볼것이다.AppDelegate는 app lifecycle 전체를 관리하는 파일이다.  AppDelegate.swift알람의 경우에는 이 AppDelegate 파일에서 만들게 된다.didFinishLaunchngWithOptions 안에

wildguess.tistory.com

 

 

이번에는 SwiftUI에서 알람을 보내는 방법이다.


우선적으로 UserNotifications 라이브러리를 불러온다.

 

그리고 기본적인 틀을 짠다.

import SwiftUI
import UserNotifications

struct ContentView: View {
    var body: some View {
        VStack {
            Button("Interval Notification"){}
            Button("Calendar Notification"){}
            Button("Location Notification"){}
        }
        .padding()
    }
    
    func requestNotificationPermission(){
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
            if granted {
                print("알림 권한이 허용되었습니다.")
            } else {
                print("알림 권한이 거부되었습니다.")
            }
            
        }
    }
}

#Preview {
    ContentView()
}

 

그리고, VStack 뒤에 onAppear로 방금 만든 메서드인 requestNotificationPermission()이 호출되도록 한다.

 

 

그리고 일단 Interval Notification을 UIKit으로부터 복사해서 해당 메서드를 만들고 내용을 채워준다.

시뮬레이터에서 확인

//
//  ContentView.swift
//  notification-test-swiftui

import SwiftUI
import UserNotifications
import CoreLocation

struct ContentView: View {
    var body: some View {
        VStack {
            Button("Interval Notification"){
                intervalTrigger()
            }
            Button("Calendar Notification"){
                calendarTrigger()
            }
            Button("Location Notification"){}
        }.onAppear(perform: {
            requestNotificationPermission()
        })
        .padding()
    }
    
    func requestNotificationPermission(){
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
            if granted {
                print("알림 권한이 허용되었습니다.")
            } else {
                print("알림 권한이 거부되었습니다.")
            }
            
        }
    }
    
    func intervalTrigger(){
        let content = UNMutableNotificationContent()
        content.title = "Interval Notification"
        content.subtitle = "This is a subtitle"
        content.body = "설정하신 인터벌 노티피케이션을 알려드립니다."
        content.userInfo = ["name": "정년이"]
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false)
        
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request) {
            (error) in
            if let error {
                print("알림설정에 실패했습니다.")
            }
            print("알림설정에 성공했습니다.")
        }
        
    }
    
    func calendarTrigger(){
        let content = UNMutableNotificationContent()
        content.title = "Calendar Notification"
        content.subtitle = "This is a subtitle"
        content.body = "설정하신 캘린더 노티피케이션을 알려드립니다."
        content.userInfo = ["name": "정년이"]
        
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
        
        
        var dateComponents = DateComponents()
    
        dateComponents.hour = 14
        dateComponents.minute = 56
        
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
    }
    
    func locationTrigger(){
        let content = UNMutableNotificationContent()
        content.title = "Location Notification"
        content.subtitle = "This is a subtitle"
        content.body = "설정하신 위치 기반 노티피케이션을 알려드립니다."
        content.userInfo = ["name": "정년이"]
        
        let center = CLLocationCoordinate2D(latitude: 37, longitude: -122)
        let region = CLCircularRegion(center: center, radius: 1000, identifier: "iOS study")
        
        region.notifyOnEntry = true
        region.notifyOnExit = true
        
        let trigger = UNLocationNotificationTrigger(region: region, repeats: true)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
    }
}

#Preview {
    ContentView()
}

AppDelegate

아까 UIKit의 경우, app lifecycle을 관리하는 AppDelegate에 Notification을 정의해주었는데, SwiftUI의 경우 AppDelegate 파일이 없으므로, 기본 파일 앱에 AppDelegate를 만들어주어야한다.

프로젝트 생성 시, 내가 설정한 프로젝트 이름과 동일하게 생성되는 SwiftUI파일에 간다.

 

notification_test_swiftuiApp.swift

그리고 AppDelegate를 사용하려면,   @UIApplicationDelegateAdaptor 데코레이터를 사용해줘야 한다.

 

 

그리고 아래에 AppDelegate 클래스를 생성해준다.

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }

 

 

그리고 해당 AppDelegate 내부에 UIKit의 AppDelegate에서 복사를 해서 붙여준다.

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let info = notification.request.content.userInfo
        print(info["name"] ?? "")
        completionHandler([.banner, .sound])
    }
    
    // 유저 알람 클릭 액션 -> 앱으로 접속
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let info = response.notification.request.content.userInfo
        print(info["name"] ?? "")
        completionHandler()
        
    }

 

 

 

 

테스트

 

 


최종 코드

notification_test_swiftuiApp.swift

import SwiftUI

@main
struct notification_test_swiftuiApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let info = notification.request.content.userInfo
        print(info["name"] ?? "")
        completionHandler([.banner, .sound])
    }
    
    // 유저 알람 클릭 액션 -> 앱으로 접속
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let info = response.notification.request.content.userInfo
        print(info["name"] ?? "")
        completionHandler()
        
    }
    
}

 

 

ContentView.swift

//
//  ContentView.swift
//  notification-test-swiftui
//
//

import SwiftUI
import UserNotifications
import CoreLocation

struct ContentView: View {
    var body: some View {
        VStack {
            Button("Interval Notification"){
                intervalTrigger()
            }
            Button("Calendar Notification"){
                calendarTrigger()
            }
            Button("Location Notification"){}
        }.onAppear(perform: {
            requestNotificationPermission()
        })
        .padding()
    }
    
    func requestNotificationPermission(){
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
            if granted {
                print("알림 권한이 허용되었습니다.")
            } else {
                print("알림 권한이 거부되었습니다.")
            }
            
        }
    }
    
    func intervalTrigger(){
        let content = UNMutableNotificationContent()
        content.title = "Interval Notification"
        content.subtitle = "This is a subtitle"
        content.body = "설정하신 인터벌 노티피케이션을 알려드립니다."
        content.userInfo = ["name": "정년이"]
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false)
        
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request) {
            (error) in
            if let error {
                print("알림설정에 실패했습니다.")
            }
            print("알림설정에 성공했습니다.")
        }
        
    }
    
    func calendarTrigger(){
        let content = UNMutableNotificationContent()
        content.title = "Calendar Notification"
        content.subtitle = "This is a subtitle"
        content.body = "설정하신 캘린더 노티피케이션을 알려드립니다."
        content.userInfo = ["name": "정년이"]
        
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
        
        
        var dateComponents = DateComponents()
    
        dateComponents.hour = 15
        dateComponents.minute = 28
        
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
    }
    
    func locationTrigger(){
        let content = UNMutableNotificationContent()
        content.title = "Location Notification"
        content.subtitle = "This is a subtitle"
        content.body = "설정하신 위치 기반 노티피케이션을 알려드립니다."
        content.userInfo = ["name": "정년이"]
        
        let center = CLLocationCoordinate2D(latitude: 37, longitude: -122)
        let region = CLCircularRegion(center: center, radius: 1000, identifier: "iOS study")
        
        region.notifyOnEntry = true
        region.notifyOnExit = true
        
        let trigger = UNLocationNotificationTrigger(region: region, repeats: true)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
    }
}

#Preview {
    ContentView()
}

 

Comments