2

I'm looking for a way to present notifications on even (2,4,6,8,10,12...) & odd (1,3,5,7,9,11...) days.

I did something similar in reminders:

/// Creates a reminder
func create(_ title: String, isOddDays: Bool, hour: Int, minute: Int) {
    let dueDate = Date()
    let gregorian = Calendar(identifier: .gregorian)
    
    let daysOfTheMonth: [NSNumber]
    if isOddDays {
        daysOfTheMonth = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
    } else {
        daysOfTheMonth = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
    }
    
    let rule = EKRecurrenceRule(
        recurrenceWith: .monthly,
        interval: 1,
        daysOfTheWeek: nil,
        daysOfTheMonth: daysOfTheMonth,
        monthsOfTheYear: nil,
        weeksOfTheYear: nil,
        daysOfTheYear: nil,
        setPositions: nil,
        end: nil
    )
    
    guard let reminder: EKReminder = self.setUpReminder(with: title, priority: 0) else {
        return
    }
    
    reminder.dueDateComponents = gregorian.dateComponents([.day, .month, .year, .hour, .minute, .second], from: dueDate)
    reminder.addRecurrenceRule(rule)
    
    let todayDateComponents = gregorian.dateComponents([.day, .month, .year], from: Date())
    let day: Int = isOddDays ? 1 : 2
    let month: Int = todayDateComponents.month!
    let year: Int = todayDateComponents.year!
    
    let absoluteDate = Date.create(day: day, month: month, year: year, hour: hour, minute: minute, second: 0)
    
    let alarm = EKAlarm(absoluteDate: absoluteDate)
    reminder.addAlarm(alarm)
    
    UserDefaults.standard.set(reminder.calendarItemIdentifier, forKey: ReminderStoreManager.reminderDefaultsKey)
    
    self.saveReminder(reminder)
}

I want to do something similar with local notifications in order to send an acknowledgment back to the server.

EDIT: Screenshot added. enter image description here

Idan Moshe
  • 1,675
  • 4
  • 28
  • 65
  • You can do the same thing with EKEvent. It has a *open URL* alarm type. Attach a script (AppleScript or Swift) to the alarm which creates and delivers the notification at the moment the alarm fires. – vadian Nov 10 '22 at 08:45
  • Thanks, but that's too complicated since I need to remove reminders when the user removes the app from the device. – Idan Moshe Nov 10 '22 at 12:09
  • 1
    Recommend to have a read here: https://developer.apple.com/documentation/usernotifications/scheduling_a_notification_locally_from_your_app – invzbl3 Nov 15 '22 at 21:48

2 Answers2

2

Apparently I can use DateComponents without month & year and It will do the rest:

private func scheduleEveryTwoDaysNotification(prefix: String, isOddDay: Bool, title: String, triggerDate: Date) {
    let triggerDateComponents = Calendar.current.dateComponents([.day, .month, .year, .hour, .minute], from: triggerDate)
    
    guard let hour = triggerDateComponents.hour, let minute = triggerDateComponents.minute else {
        return
    }
    
    let days: [Int]
    if isOddDay {
        days = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
    } else {
        days = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
    }
    
    for day in days {
        let content = UNMutableNotificationContent()
        content.title = title
        content.sound = .default
        
        var components = DateComponents()
        components.day = day
        components.hour = hour
        components.minute = minute
        components.second = 0
        
        
        let calendarTrigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
        let identifier: String = "\(prefix).\(day)"
        let request = UNNotificationRequest(identifier: identifier, content: content, trigger: calendarTrigger)
        
        UNUserNotificationCenter.current().add(request) { (error) in
            if let error {
                debugPrint(#fileID, #function, error)
            } else {
                debugPrint(#function, request)
            }
        }
    }
}
Idan Moshe
  • 1,675
  • 4
  • 28
  • 65
0

Something like:

import Foundation

func isThisAnEvenDay() -> Bool {
    Calendar.current.component(.day, from: Date()) % 2 == 0
}

print(isThisAnEvenDay())

Didn't work for you? Then you present your notification immediately, without the need to schedule ahead.

Don't know if is something like this you are looking for.

Allan Garcia
  • 550
  • 3
  • 16