ios - 如何让一个常规对象类做自己的事情是 NSManagedObject 的子类?

标签 ios swift extension-methods

目前,我有两个不同的类,Alarm 和 AlarmMO,AlarmMO 是 NSManagedObject 的子类。如果可能的话,我试图将这两个组合成一个对象类,但我遇到了一些麻烦。最好的方法是如何做到这一点?

这是我目前所拥有的,但我遇到了各种各样的错误:

class Alarm: NSManagedObject {

    //MARK: Properties
    @NSManaged var alarmTime: Double
    @NSManaged var alarmNumber: Int
    @NSManaged var startTimeInterval: Double
    @NSManaged var endTimeInterval: Double
    @NSManaged var note: String
    @NSManaged var notificationUuids: [String]
    @NSManaged var recurrenceIndex: Int
    var recurrence: RecurrenceOptions = .today
    let NUMBER_OF_ALLOWED_NOTIFICATIONS_CREATED_AT_ONE_TIME = 10

}

extension Alarm {

convenience init?(alarmNumber: Int, timeIntervals: TimeIntervals, note: String, recurrence: RecurrenceOptions) {

    self.alarmNumber = alarmNumber
    self.note = note
    self.recurrence = recurrence
    self.notificationUuids = [String]()

    let date = Date()
    let calendar = Calendar.current
    let currentDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: date)
    var dateComponents = DateComponents()
    dateComponents.year = currentDateComponents.year
    dateComponents.month = currentDateComponents.month
    dateComponents.timeZone = currentDateComponents.timeZone
    dateComponents.day = currentDateComponents.day

    let startInterval = Alarm.convertToTimeDouble(hour: timeIntervals.hourStartInterval, minute: timeIntervals.minuteStartInterval)
    let endInterval = Alarm.convertToTimeDouble(hour: timeIntervals.hourEndInterval, minute: timeIntervals.minuteEndInterval)
    self.startTimeInterval = startInterval
    self.endTimeInterval = endInterval
    if endInterval < startInterval {
        os_log("Error: Alarm time endInterval is before startInterval", log: OSLog.default, type: .info)
        return nil
    }
    self.alarmTime = Double.random(in: startInterval ... endInterval)

    let hour = Alarm.extractHourFromTimeDouble(alarmTimeDouble: self.alarmTime)
    let minute = Alarm.extractMinuteFromTimeDouble(alarmTimeDouble: self.alarmTime)
    os_log("Attempting to create alarm with time %d:%02d", log: OSLog.default, type: .info, hour, minute)

    createNotifications(dateComponents: dateComponents)

}

public static func convertToTimeDouble(hour: Int, minute: Int) -> Double {

    return Double(hour) + (Double(minute) / 60.0)

}

public static func extractHourFromTimeDouble(alarmTimeDouble: Double) -> Int {

    return Int(floor(alarmTimeDouble))

}

public static func extractMinuteFromTimeDouble(alarmTimeDouble: Double) -> Int {

    return Int(round((alarmTimeDouble - floor(alarmTimeDouble)) * 60))

}

func createNotifications(dateComponents: DateComponents) {

    switch (self.recurrence) {
    case .today:
        self.createNotification(for: dateComponents)
    case .tomorrow:
        self.createNotification(for: self.day(after: dateComponents))
    case .daily:
        var numberOfCreatedNotifications = 0
        var currentDay: DateComponents? = dateComponents
        while numberOfCreatedNotifications < self.NUMBER_OF_ALLOWED_NOTIFICATIONS_CREATED_AT_ONE_TIME {
            self.createNotification(for: currentDay)
            currentDay = self.day(after: currentDay)
            numberOfCreatedNotifications += 1
        }
    }

}

//MARK: Private functions

private func createNotification(for dateComponents: DateComponents?) {

    let center = UNUserNotificationCenter.current()

    let content = UNMutableNotificationContent()
    content.title = "Random Alarm"
    content.subtitle = "It's time!"
    content.body = self.note
    content.sound = UNNotificationSound.default

    guard let dateComponents = dateComponents else {
        os_log("Could not unwrap dateComponents in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
        return
    }
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

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

    guard let day = dateComponents.day else {
        os_log("Could not unwrap dateComponents.day in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
        return
    }
    guard let hour = dateComponents.hour else {
        os_log("Could not unwrap dateComponents.hour in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
        return
    }
    guard let minute = dateComponents.minute else {
        os_log("Could not unwrap dateComponents.minute in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
        return
    }
    os_log("Creating notification for day: %d, time: %d:%02d, with uuid=%s", log: OSLog.default, type: .debug, day, hour, minute, uuidString)

    center.add(request) { (error) in
        if let err = error {
            print("error \(err.localizedDescription)")
        }
    }
}

private func day(after dateComponents: DateComponents?) -> DateComponents? {

    let calendar = Calendar.autoupdatingCurrent

    guard let dateComponents = dateComponents,
        let date = calendar.date(from: dateComponents),
        let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
        else {
            os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
            return nil
    }
    let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
    return newDateComponents

}

}

最佳答案

如果 AlarmMO 是您在 Core Data 中的实体,那么应该为您创建 AlarmMO 对象。您可以使用扩展来添加您需要的任何其他行为。

虽然您可以创建一个新的初始化程序,但我可能会采用使用静态函数的工厂方法:

extension AlarmMO {

    static func newAlarm(context: NSManagedObjectContext, alarmNumber: Int, timeIntervals: TimeIntervals, note: String, recurrence: RecurrenceOptions) -> AlarmMO? {

        let startInterval = Alarm.convertToTimeDouble(hour: timeIntervals.hourStartInterval, minute: timeIntervals.minuteStartInterval)
        let endInterval = Alarm.convertToTimeDouble(hour: timeIntervals.hourEndInterval, minute: timeIntervals.minuteEndInterval)

        if endInterval < startInterval {
            os_log("Error: Alarm time endInterval is before startInterval", log: OSLog.default, type: .info)
            return nil
        }
        let newAlarm = AlarmMO(context: context)
        newAlarm.alarmNumber = alarmNumber
        newAlarm.note = note
        newAlarm.recurrence = recurrence
        newAlarm.notificationUuids = [String]()
        newAlarm.alarmTime = Double.random(in: startInterval ... endInterval)
        newAlarm.startTimeInterval = startInterval
        newAlarm.endTimeInterval = endInterval

        return newAlarm
    }

    var recurrence: RecurrenceOptions {
        get {
            return RecurrenceOptions(rawValue: self.recurrenceIndex)!
        }

        set {
            self.recurrenceIndex = newValue.rawValue
        }
    }

    var hour: Int {
        return Int(floor(self.alarmTime))
    }

    var minute: Int {
        return Int(round((self.alarmTime - floor(self.alarmTime)) * 60))
    }

    func scheduleNotification() {
        os_log("Attempting to create alarm with time %d:%02d", log: OSLog.default, type: .info, self.hour, self.minute)
        let date = Date()
        let calendar = Calendar.current
        let currentDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: date)
        var dateComponents = DateComponents()
        dateComponents.year = currentDateComponents.year
        dateComponents.month = currentDateComponents.month
        dateComponents.timeZone = currentDateComponents.timeZone
        dateComponents.day = currentDateComponents.day
        createNotifications(dateComponents: dateComponents)
    }


    // Note:  This probably should be in TimeIntervals, rather than here
    public static func convertToTimeDouble(hour: Int, minute: Int) -> Double {
        return Double(hour) + (Double(minute) / 60.0)
    }

关于ios - 如何让一个常规对象类做自己的事情是 NSManagedObject 的子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53789796/

相关文章:

swift - 如何从同一 ViewController 的扩展访问 var

ios - 如何使用vDSP_conv来模拟MATLAB的xcorr函数?

ios - 在基于 View 的应用程序中使用 UITabBar 不起作用

ios - objective-c 中的类扩展

ios - 设置UIImageView图像后多次调用CFRunLoopRun

swift - 无法将字典提取为 [String : Any] from vapor request context

java - JVM:Scala 的 JavaConversions 如何在 Java 代码中工作?

ios - 从 strftime 获取 NSString

ios - 将数组 int 附加到字符串数组

c# - 扩展方法中 `this`参数为null时应该抛出什么?