나의 발자취
[SwiftUI] Remote Push Notification Alert 구현 (feat.APNs) 본문
지난 프로젝트에 이어서
2024.11.21 - [분류 전체보기] - [SwiftUI] Notification 기능 구현하기
didRegister...을 만들어준다.
그리고 이 안에는 아까 UIKit의 내용을 붙여넣는다.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token: String = ""
for i in 0..<deviceToken.count {
token += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
}
print("APNs token: \(token)")
// 토큰 저장
UserDefaults.standard.set(token, forKey: "token") // 저장해놨다가 로그인했을 때 id와 같이 토큰을 서버에 등록하는 것
}
다음,
ContentView.swift에 있는 requestNotificationPermission()을 잘라내서 붙여넣어준다.
그리고 이렇게 함수로 따로 빼줬으니, didFinishLaunchingWithOptions 에서는 requestNotificationPermission() 메서드를 호출해주어야 한다. (line 23)
그리고 역시나 똑같이 granted 조건 실행문에는 DispatchQueue로 푸쉬 알림을 실행해준다.
이제 앱을 빌드해주고, 터미널창에 나온 APNs 토큰을 복사해서 Postman에 넣어준다.
<주의>
UiKit, SwiftUI 용 프로젝트를 각각 만들었으므로, bundle id가 다르기 때문에 백엔드의 .env에서도 BUNDLE_ID 값이 변경될 것이다. 이 렇게 해당 값이 변경될 경우는 서버를 내렸다가 다시 올려줘야한다.
그렇지 않으면 400 코드가 뜨면서 DeviceTokenNotForTopic 에러가 뜰 것이다.
노드몬 서버를 다시 내렸다가 실행해주면 아래와 같이 푸쉬 알림이 잘 오는 걸 볼 수 있다.
최종 코드
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
requestNotificationPermission()
return true
}
func requestNotificationPermission(){
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
if granted {
print("알림 권한이 허용되었습니다.")
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
print("알림 권한이 거부되었습니다.")
}
}
}
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()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token: String = ""
for i in 0..<deviceToken.count {
token += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
}
print("APNs token: \(token)")
// 토큰 저장
UserDefaults.standard.set(token, forKey: "token") // 저장해놨다가 로그인했을 때 id와 같이 토큰을 서버에 등록하는 것
}
}
ContentView.swift
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 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()
}
'앱 개발 > iOS' 카테고리의 다른 글
Alamofire에서 데이터 가져올때의 데이터 프로퍼티 접근 (0) | 2024.12.13 |
---|---|
SwiftUI 텍스트 굵기 수정자 (0) | 2024.12.05 |
[SwiftUI] Social Login 기능 도입하기 - KaKao (1) | 2024.11.27 |
[SwiftUI] Social Login 기능 도입하기 - Apple (0) | 2024.11.26 |
[UIKit] Remote Push Notification Alert 구현 (feat.APNs) (0) | 2024.11.22 |
Comments