23

ドキュメントから:

fireDate で指定された日付は、このプロパティの値に従って解釈されます。nil (デフォルト) を指定すると、起動日は絶対 GMT 時間として解釈され、カウントダウン タイマーなどの場合に適しています。有効な NSTimeZone オブジェクトをこのプロパティに割り当てた場合、開始日は実時間として解釈され、タイム ゾーンが変更されたときに自動的に調整されます。この場合に適した例は、目覚まし時計です。

明日の正午 (絶対時間) GMT にローカル通知をスケジュールするとします。これをシアトルで午後 1 時 (太平洋時間、GMT-8) にスケジュールし、すぐにシカゴに移動して午後 11 時 (中部時間、GMT-6) に到着します。私のデバイスは太平洋時間から中央時間に調整されます。次の 3 つのケースで、いつ通知が行われるかを理解するのを手伝ってください。

  1. UILocalNotification timeZone が nil に設定されました。
  2. UILocalNotification timeZone が GMT に設定されました。
  3. UILocalNotification timeZone が太平洋時間に設定されました。
4

3 に答える 3

43

iOS 6.1.3 でいくつかのテストを実行しました。これが私が得たものです:

私は午後 1 時 (太平洋夏時間、GMT-7) にシアトルにいます。私が作成したNSDate

NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
// 2013-08-31 @ 12:00:00 (noon)
dateComponents.year = 2013;
dateComponents.month = 8;
dateComponents.day = 31;
dateComponents.hour = 12;
dateComponents.minute = 0;
dateComponents.second = 0;

NSDate *fireDate = [gregorianCalendar dateFromComponents:dateComponents];

今私が持っています

fireDate = 2013-08-31 19:00:00 +0000 (2013-08-31 12:00:00 -0700)

次に、通知を作成してスケジュールしました。

notification1 = [[UILocalNotification alloc] init];
notification1.fireDate = fireDate;
// notification1.timeZone is nil by default

NSLog(@"%@", notification1);

notification2 = [[UILocalNotification alloc] init];
notification2.fireDate = fireDate;
notification2.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];

NSLog(@"%@", notification2);

notification3 = [[UILocalNotification alloc] init];
notification3.fireDate = fireDate;
notification3.timeZone = [NSTimeZone defaultTimeZone];

NSLog(@"%@", notification3);

シアトル (太平洋夏時間、GMT-7) で作成された通知のログ:

notification1:
fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time,
time zone = (null),
next fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time

notification2:
fire date = Saturday, August 31, 2013, 7:00:00 PM GMT,
time zone = GMT (GMT) offset 0,
next fire date = Saturday, August 31, 2013, 7:00:00 PM Pacific Daylight Time

notification3:
fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time,
time zone = US/Pacific (PDT) offset -25200 (Daylight),
next fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time

電話のタイムゾーンをシカゴに変更しました。現在は午後 3 時 (中央夏時間、GMT-5) です。

通知のログ、シカゴ (中央夏時間、GMT-5)

notification1:
fire date = Saturday, August 31, 2013, 2:00:00 PM Central Daylight Time,
time zone = (null),
next fire date = Saturday, August 31, 2013, 2:00:00 PM Central Daylight Time

notification2:
fire date = Saturday, August 31, 2013, 7:00:00 PM GMT,
time zone = GMT (GMT) offset 0,
next fire date = Saturday, August 31, 2013, 7:00:00 PM Central Daylight Time

notification3:
fire date = Saturday, August 31, 2013, 12:00:00 PM Pacific Daylight Time,
time zone = US/Pacific (PDT) offset -25200 (Daylight),
next fire date = Saturday, August 31, 2013, 12:00:00 PM Central Daylight Time

結論:

  1. UILocalNotificationtimeZoneが nil の場合、起動日は時間内に固定されます。つまり、通知は 12:00PM GMT-7、2:00PM GMT-5、または 7:00 GMT に発生します。
  2. UILocalNotificationtimeZoneが GMT に設定されている場合、起動日は GMT 時間で計算され、ユーザーが別のタイム ゾーンに移動すると自動更新されます。この例では、時刻 12:00 GMT-7 が 19:00 GMT に変換され、通知は 19:00 現地時間に設定され、タイム ゾーン (19:00 GMT、19:00 GMT-5 または19:00 GMT-7)。
  3. UILocalNotificationtimeZoneがローカル タイム ゾーン (太平洋夏時間、GMT-7) に設定されている場合、起動日はローカル タイムに対して計算され、ユーザーが別のタイム ゾーンに移動すると自動更新されます。この例では、時間は 12:00 GMT-7 だったので、タイムゾーンに関係なく (12:00 GMT、12:00 GMT-5、または 12:00 GMT- 7)。
于 2013-08-30T19:34:28.750 に答える
2

iOS 13 で UNCalendarNotificationTrigger を使用する Swift 5.2

で同じことをするためのインスピレーションとして @brnunes コードを使用しましたUNCalendarNotificationTrigger

TimeZone.autoupdatingCurrent現地時間に通知を送信する場合に使用します。例: 午後 6 時 GMT に通知をスケジュールし、デバイスのタイム ゾーンを CET に変更しても、デバイスの通知は引き続き午後 6 時にスケジュールされます。

時間内に固定された発火日が必要な場合は、TimeZone.currentまたはのような他のタイム ゾーンを使用します。TimeZone.init(abbreviation: "GMT")例: 東部夏時間 (EDT GMT-4) の午後 2 時に通知をスケジュールし、デバイスのタイム ゾーンを CEST (GMT+2) に変更すると、デバイスの通知は午後 8 時にスケジュールされます。GMT の午後 6 時に会議を行うようなものです。ミーティングの時間は変わりません。EDT は午後 2 時、CEST は午後 8 時です。

次のコードを使用して通知を追加しました。

func addNotification(identifier: String, timeZone: TimeZone?) {
    let content = UNMutableNotificationContent()
    content.title = "Title \(identifier)"
    content.body = "Body"

    let trigger = UNCalendarNotificationTrigger(
        dateMatching: DateComponents(
            calendar: Calendar.current,
            timeZone: timeZone,
            year: 2020,
            month: 04,
            day: 01,
            hour: 18,
            minute: 30,
            second: 0),
        repeats: false)

    let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)

    UNUserNotificationCenter
        .current()
        .add(request) { _ in
            print("Scheduled \(identifier)")
    }
}

4 つの異なる通知を追加しました。

addNotification(identifier: "1", timeZone: nil)
addNotification(identifier: "2", timeZone: TimeZone.init(abbreviation: "GMT")!)
addNotification(identifier: "3", timeZone: TimeZone.autoupdatingCurrent)
addNotification(identifier: "4", timeZone: TimeZone.current)

次のコードを使用して、スケジュールされたリクエストを出力しました。

UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { notificationRequests in
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .medium
    dateFormatter.timeStyle = .medium
    dateFormatter.timeZone = TimeZone.current

    print(TimeZone.current)
    notificationRequests.forEach({
        let nextTriggerDate = ($0.trigger as! UNCalendarNotificationTrigger).nextTriggerDate()!
        print("\($0.identifier): \(dateFormatter.string(from: nextTriggerDate)) (\(nextTriggerDate))")
    })
})

まず、CEST (GMT+2) でコードを実行しました。次に、iOS の設定に移動し、タイム ゾーンを EDT のマイアミ (GMT-4) に変更しました。これが結果です。

Europe/Berlin (current)
1: 1. Apr 2020 at 18:30:00 (2020-04-01 16:30:00 +0000)
2: 1. Apr 2020 at 20:30:00 (2020-04-01 18:30:00 +0000)
3: 1. Apr 2020 at 18:30:00 (2020-04-01 16:30:00 +0000)
4: 1. Apr 2020 at 18:30:00 (2020-04-01 16:30:00 +0000)

US/Eastern (current)
1: 1. Apr 2020 at 12:30:00 (2020-04-01 16:30:00 +0000)
2: 1. Apr 2020 at 14:30:00 (2020-04-01 18:30:00 +0000)
3: 1. Apr 2020 at 18:30:00 (2020-04-01 22:30:00 +0000)
4: 1. Apr 2020 at 12:30:00 (2020-04-01 16:30:00 +0000)

1、2、および 4 でわかるように、日付は決して変更されません。2020-04-01 16:30:00 +00002020-04-01 18:30:00 +0000、および2020-04-01 16:30:00 +0000です。通知が発生した現地時間のみが変更および更新されます。

3 では、実際の日付が 2020-04-01 16:30:00 +0000 から 2020-04-01 22:30:00 +0000 に変更さます。ただし、現地時間は変更されず、18:30:00のままです。

ここでわかるように、@brnunes の回答UILocalNotificationUNCalendarNotifactionTrigger. 彼の 2 番目の結論ではUILocalNotifictions、さまざまなタイム ゾーンの自動更新について述べています。ではUNCalendarNotificationTrigger、もうそうではありません。@Nicolas Buquet が指摘したように、TimeZone.autoupdatingCurrentは と同等ですdefaultTimeZone

于 2020-03-29T23:25:56.397 に答える
0

Swift 3 では、TimeZone.autoupdatingCurrentObjective-C と同じように動作するために使用します[NSTimeZone defaultTimeZone]

于 2016-11-15T10:43:31.357 に答える