كيفية الاستيلاء على موعد الحريق التالي من كائن UilocalNotification

StackOverflow https://stackoverflow.com/questions/4301184

سؤال

لدي كائن UilocalNotification الذي قمت بإعداده مع فترات متكررة اليوم والأسبوع والشهر. لا أواجه أي مشاكل على الإطلاق في الوصول إلى تاريخ نيران الكائن:

[cell.detailTextLabel setText:[notification1.fireDate description]];

لكنني أواجه مشاكل في الحصول على تاريخ الحريق التالي. إذا قمت بطباعة كائن Notification1 أعلاه إلى وحدة التحكم ، أحصل على هذا:

<UIConcreteLocalNotification: 0x613e060>{fire date = 2010-11-29 03:53:52 GMT, time zone = America/Denver (MST) offset -25200, repeat interval = 16, next fire date = 2010-11-30 03:53:52 GMT}

يحتوي هذا الكائن على القيمة أو البيانات التي أحتاجها لعرض تاريخ الحريق التالي ... لكن لا يمكنني العثور عليها! هل يعرف أي شخص أين يمكنني الحصول عليه برمجياً؟

شكرًا

هل كانت مفيدة؟

المحلول

لا أعتقد أن تاريخ الحريق التالي متاح كعقار ولكنه محسوب من fireDate و repeatInterval. يمكن أن يكون حساب التاريخ صعبًا مع مناطق زمنية مختلفة وغيرها من الأشياء السيئة. في المثال الخاص بك ، اخترت تكرارًا يوميًا ولحساب تاريخ الحريق التالي ، يمكنك القيام بشيء على غرار:

NSCalendar *calendar = localNotif.repeatCalendar;
if (!calendar) {
  calendar = [NSCalendar currentCalendar];
}

NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components.day = 1;
NSDate *nextFireDate = [calendar dateByAddingComponents:components toDate:localnotif.fireDate options:0];

إذا كنت تستخدم فترة تكرار أخرى ، فسيتعين عليك تغيير الرمز وفقًا لذلك. إذا كنت ستستخدم NSMonthCalendarUnit سيكون عليك استخدام components.month = 1 في حين أن.

نصائح أخرى

لحساب التالي تاريخ النار لتكرار UILocalNotification, ، عليك أن:

  1. اكتشف مقدار repeatInterval كان هناك بين تاريخ الحريق الأصلي للإخطار (أي أنه fireDate الممتلكات) والآن.
  2. أضفها إلى الإخطار fireDate.

هنا نهج واحد:

NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];

NSDateComponents *difference = [calendar components:notif.repeatInterval
                                           fromDate:notif.fireDate
                                             toDate:[NSDate date]
                                            options:0];

NSDate *nextFireDate = [calendar dateByAddingComponents:difference
                                                 toDate:notif.fireDate
                                                options:0];

يعمل هذا في العديد من السيناريوهات ، ولكن إليك سيناريو لا يعمل فيه:

لنفترض أن:

  • الإخطار `FireDate هو 01/01 في الساعة 2:00 مساءً
  • الإخطار repeatInterval هو NSDayCalendaryUnit (أي كرر يوميا)
  • التاريخ الآن هو 08/01 في الساعة 3:00 مساءً

سيحسب الرمز أعلاه الفرق إلى 7 أيام (01/01 + 7 أيام = 08/01) ، أضفه إلى fireDate, ، وبالتالي ضبط nextFireDate إلى 08/01 في الساعة 2 مساءً. لكن هذا في الماضي ، نريد nextFireDate أن تكون 09/01 في الساعة 2 مساءً!

لذلك إذا كنت تستخدم الرمز أعلاه و repeatInterval هو NSDayCalendaryUnit, ، ثم أضف هذه الخطوط:

if ([nextFireDate timeIntervalSinceDate:[NSDate date]] < 0) {
    //next fire date should be tomorrow!
    NSDateComponents *extraDay = [[NSDateComponents alloc] init];
    extraDay.day = 1;
    nextFireDate = [calendar dateByAddingComponents:extraDay toDate:nextFireDate options:0];
}

لقد حددت هذه الإجابة على أنها ويكي المجتمع ، لا تتردد في تحريرها إذا وجدت طريقة أفضل للقيام بالحساب!

أود فقط إضافة REPERINTERVAL حتى يكمن التاريخ في المستقبل:

-(NSDate*)nextFireDateForNotification:(UILocalNotification*)notification {
        NSCalendar *calendar = notification.repeatCalendar;
        if (!calendar) {
            calendar = [NSCalendar currentCalendar];
        }

        NSDate* date = [notification.fireDate copy];
        while (date.timeIntervalSinceNow > 0) {
            date = [calendar dateByAddingUnit:notification.repeatInterval value:1 toDate:date options:0];
        }
        return date;
    }

في هذا سريع 4 واستخدام التقويم nextDate Func.

extension UILocalNotification {

    var nextFireDate: Date? {
        guard let fireDate = fireDate else { return nil }

        let today = Date()
        let cal = Calendar.current

        if fireDate.compare(today) == .orderedDescending {
            return fireDate
        }

        let s: Set<Calendar.Component>
        switch repeatInterval {
        case .year: s = [.month, .day, .hour, .minute, .second]
        case .month: s = [.day, .hour, .minute, .second]
        case .day: s = [.hour, .minute, .second]
        case .hour: s = [.minute, .second]
        case .minute: s = [.second]
        default: return nil // Not supporting other intervals
        }

        let components = cal.dateComponents(s, from: fireDate)
        return cal.nextDate(after: today, matching: components, matchingPolicy: .nextTimePreservingSmallerComponents)
    }

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top