작성
·
194
0
예제를 전부 구현한 상태에서
아래 코드를 통해서 뱃지 숫자를 1씩 올려서 보내게
되어 있습니다.
func scheduleNotification() {
//notification 내용 설정
let content = UNMutableNotificationContent()
content.title = "Local Notification 테스트 1"
content.subtitle = "앱 알람 테스트 중입니다."
content.sound = .default
content.badge = NSNumber(value: UIApplication.shared.applicationIconBadgeNumber + 1)
하지만 아래 코드에 의해 뱃지가 0 으로 리셋되기에
항상 1만 발송하게 됩니다.
.onChange(of: scenePhase) { newValue in
if newValue == .active {
UIApplication.shared.applicationIconBadgeNumber = 0
}
}
추가적으로 5초 딜레이로 설정후 로컬노티 여러번 누른후에
앱을 종료하고 기다리면 노티가 여러개 오지만
모두 뱃지 1로 오기 때문에 앱아이콘에 뱃지는 1로 계속
옵니다.
실무에서 로컬노티에 카운터를 현재 뱃지 카운터에 + 1 해서
보내는건 실효성이 없어보이는데요.
따로 해결할 방법이 있을까요 ? 조언 부탁드립니다.
강의 관련된 질문은 언제나 환영입니다 😄
코드 관련 상세하게 작성해주시면 더 좋아요! (상세코드를 붙여넣기 해주세요)
마크다운을 사용해서 편리하게 글을 작성하세요
먼저 유사한 질문이 있었는지 먼저 검색 해보는 습관~
인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요
답변 2
1
안녕하세요 랑프님.
앱이 활성화될 때마다 UIApplication.shared.applicationIconBadgeNumber = 0
으로 뱃지가 초기화되므로, 로컬 알림을 여러 번 발송해도 모든 알림이 뱃지 값이 1인 상태로 도착합니다. 이는 알림의 뱃지 값이 항상 초기화되기 때문에 발생합니다.
이를 해결하기 위해서 UserDefaults 를 사용해서 뱃지 값을 저장하고 불러오는 방법을 사용하면 됩니다.
수정된 코드는 다음과 같습니다. *수정한 부분만 사진으로 올려드리고 전체 코드는 맨아래 있습니다.
앱이 종료 되어도 뱃지값 저장하기
CancelNotifiactaion 에서 값 초기화
View에서 화면이 나타날때 reset 하는거 삭제
수정된 코드
class NotificationManager {
static let instance = NotificationManager() // 인스턴스 생성
func requestAuthorization() {
let option: UNAuthorizationOptions = [.alert, .sound, .badge]
// UserNotification 접근
UNUserNotificationCenter.current().requestAuthorization(options: option) { (success, error) in
if let error = error {
print("에러: \(error)")
} else {
print("성공")
}
}
}
func scheduleNotification() {
// UserDefaults 에다가 자장할 currentBadgeCount
let currentBadgeCount = UserDefaults.standard.integer(forKey: "badgeCount")
// 값을 1씩 증가 시킴
let newBadgeCount = currentBadgeCount + 1
// 증가한다음에서는 값을 저장
UserDefaults.standard.set(newBadgeCount, forKey: "badgeCount")
// notification 내용 설정
let content = UNMutableNotificationContent()
content.title = "Local Notification 테스트 1"
content.subtitle = "앱 알람 테스트 중입니다"
content.sound = .default
content.badge = NSNumber(value: newBadgeCount) // 1씩 증가 시킴
// Trigger 2가지 종류
// 1.시간 기준 : Interval - 몇 초 뒤에 울릴것인지 딜레이 설정 repeats 반복 여부 설정 (최소 1분이여지 반복이 돔)
let timeTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 5.0, repeats: false)
// 2.날짜 기준 : DateMating 은 DateComponent 기준맞는 알림
var dateComponents = DateComponents()
dateComponents.hour = 8 // hour 를 24시간 기준
dateComponents.minute = 30
dateComponents.weekday = 1 // 1은 일요일이 되고, 6은 금요일이 됨
// let calendarTigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
// 설정한 값을 NotificationCenter 에 요청하기
let request = UNNotificationRequest(
identifier: UUID().uuidString, // 각각의 request ID 값 String 을 uuid 값으로 설정
content: content,
trigger: timeTrigger)
UNUserNotificationCenter.current().add(request)
}
// 생성된 Notification Cancel 하기
func cancelNotification() {
// peding notification 은 tigger 상에서 만족된 조건이 되어도 더이상 notification 되지 않게 하기
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
// 아이폰 상태바를 내렸을때 남아있는 notification 없애기
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
// Cancel 하면 UserDefault 값 초기화 하기
UserDefaults.standard.set(0, forKey: "badgeCount")
UIApplication.shared.applicationIconBadgeNumber = 0
}
}
struct LocalNotificationInter: View {
@Environment(\.scenePhase) var scenePhase
var body: some View {
VStack (spacing: 40) {
Button {
NotificationManager.instance.requestAuthorization()
} label: {
Text("권한 요청하기")
.font(.title2)
.fontWeight(.semibold)
.foregroundColor(.black)
.padding()
.background(Color.green)
.cornerRadius(10)
}
Button {
NotificationManager.instance.scheduleNotification()
} label: {
Text("Time Notification")
.font(.title2)
.fontWeight(.semibold)
.foregroundColor(.black)
.padding()
.background(Color.green)
.cornerRadius(10)
}
Button {
NotificationManager.instance.scheduleNotification()
} label: {
Text("Calendar Notification")
.font(.title2)
.fontWeight(.semibold)
.foregroundColor(.black)
.padding()
.background(Color.green)
.cornerRadius(10)
}
Button {
NotificationManager.instance.cancelNotification()
} label: {
Text("Notification 취소하기")
.font(.title2)
.fontWeight(.semibold)
.foregroundColor(.black)
.padding()
.background(Color.green)
.cornerRadius(10)
}
} //: VSTACK
// schne 이 나타 날때 Badge 0 으로 초기화 하기
.onChange(of: scenePhase) { newValue in
if newValue == .active {
// 0으로 초기화 되지 않게 reset 하지 않기
// UIApplication.shared.applicationIconBadgeNumber = 0
}
}
}
}
0
안녕하세요, 인프런 AI 인턴입니다.
랑프_Langpeu님의 질문에 대해 답변 드리겠습니다.
문제의 핵심은 앱이 활성 상태로 전환될 때 뱃지 숫자가 0으로 초기화되어, 로컬 알림으로 설정한 뱃지 숫자가 기대와 다르게 작동한다는 점입니다.
이문제를 해결하기 위해서는 애플리케이션이 활성 상태가 될 때마다 뱃지 숫자를 초기화하지 않고, 알림을 확인하거나 필요한 조치를 취했을 때 명시적으로 뱃지 숫자를 조정하는 로직을 구현해야 합니다.
전송되는 알림의 뱃지 숫자를 올바르게 관리하기 위해서는 애플리케이션 내부적으로 알림이 몇 번 전송되었는지를 추적할 필요가 있습니다. 이를 위해, 앱의 로컬 저장소나 데이터 베이스를 사용하여 알림이 발송될 때마다 카운터를 증가시키고, 앱이 활성화될 때 해당 카운터를 참조하여 UIApplication.shared.applicationIconBadgeNumber
을 올바르게 설정하시는 것이 좋습니다.
예를 들어, 알림 발송 함수 내에서 뱃지 숫자를 증가시키는 로직을 추가하고:
func increaseBadgeNumberByOne() {
let currentBadgeNumber = UserDefaults.standard.integer(forKey: "badgeNumber")
UserDefaults.standard.set(currentBadgeNumber + 1, forKey: "badgeNumber")
content.badge = NSNumber(value: currentBadgeNumber + 1)
}
앱이 활성 상태가 될 때 뱃지 숫자를 리셋하는 대신 사용자가 알림을 확인하였다는 가정하에 뱃지 숫자를 관리할 수 있는 로직을 추가합니다:
.onChange(of: scenePhase) { newValue in
if newValue == .active {
// 사용자가 알림을 확인했다고 가정하고 뱃지 숫자를 초기화
UserDefaults.standard.set(0, forKey: "badgeNumber")
UIApplication.shared.applicationIconBadgeNumber = 0
}
}
이렇게 변경하면 앱이 활성화될 때마다 뱃지 숫자가 초기화되는 문제를 보완할 수 있습니다. 단, 이러한 방법은 알림이 발송될 때마다 앱 내부에서 뱃지 숫자를 관리해야 한다는 추가적인 구현이 필요합니다.
실제로 이 외에도 다양한 방법과 조건에 따라 뱃지 숫자를 관리할 수 있으므로, 애플리케이션의 특성과 필요에 맞게 적절한 로직을 설계하는 것이 중요할 것입니다.
답변 감사합니다.