Ваша ошибка обнаруживается, когда вы говорите следующее: "кажется, что у него где-то не установлен часовой пояс, потому что с другими методами (т.е. [NSDate date]
) событие создается успешно."
Нет NSDate
содержит информацию о часовом поясе. Все они ссылаются на GMT. Класс NSDateFormatter
обычно используется для представления их в местном часовом поясе. И, судя по вашему ответу на комментарии выше, я сомневаюсь, что вы мне сейчас верите Проверьте это, в каком-нибудь методе где-нибудь запустите эту строку кода.
NSLog(@"[NSDate date] = %@",[NSDate date]);
Согласно вашему профилю пользователя вы находитесь в Эстонии. По моему быстрому поиску вы должны быть GMT + 2: 00 (извините, если я ошибаюсь в вашем часовом поясе), поэтому время, которое вы видите в консоли, должно быть на 2 часа меньше. И я уверен, что это так. Так же, как у меня, на 5 часов вперед.
Вы также можете сказать, что я прав по вашему решению: "Мое решение заключалось в преобразовании NSDate в CFGregorianDate, установке часового пояса и обратном преобразовании. Кажется, это немного долго."
Так что в основном вы настроили часовой пояс, и он работает нормально, имеет смысл.
Но на ваш реальный вопрос: «Может ли кто-нибудь предложить более надежный способ решения этой проблемы?» Ответ относительно прост.
Допустим, ваш сервер возвращает интервал времени с 1970 года по эстонскому времени (Восточная Европа?). Все, что вам нужно сделать, это настроить этот интервал времени, чтобы указать время по Гринвичу. Опять же, если я ошибаюсь в особенностях вашего часового пояса, я прошу прощения.
NSTimeInterval estoniaTimeZoneDifference = 60*60*2;//60 seconds, 60 minutes, 2 hours
NSDate *adjusted = [NSDate dateWithTimeIntervalSince1970:(timeIntervalSince1970FromServer - estoniaTimeZoneDifference)];
// Here we subtract because this zone is 2 hours ahead of GMT.
Снова эта корректировка будет проиндексирована с ответом сервера.
Редактировать: В ответ на:
Я согласен с некоторыми пунктами вашего ответа, но постараюсь создать событие на
дата, которую вы только что создали, держу пари, ваши шансы сделать это не очень
хорошо.
По словам известного телевизионного персонажа "Вызов принят!".
Поэтому я решил проверить, может ли событие быть успешно создано с использованием dateWithTimeIntervalSince1970:
. И, как я и ожидал, я не нашел недостатка в NSDate или в структуре EventKit. Я использовал этот код:
NSTimeInterval rightNowInterval = [[NSDate date] timeIntervalSince1970];
//NSTimeInterval is a double, thus nothing up my sleeve.
NSTimeInterval intervalSince70ToFire = rightNowInterval + 120;
// Two minutes from whenever now is. Plus this is another layer of indirection to prove there's no 'magic' to [NSDate date]
//Create fire date from dateWithTimeIntervalSince1970
NSDate *fireDate = [NSDate dateWithTimeIntervalSince1970:intervalSince70ToFire];
// Insert boilerplate event code
EKEventStore *eventSotre = [[EKEventStore alloc] init];
EKEvent *event = [EKEvent eventWithEventStore:eventSotre];
event.title= @"Event Title";
event.startDate = fireDate;
event.endDate= [[NSDate alloc] initWithTimeInterval:600 sinceDate:event.startDate];
[event addAlarm:[EKAlarm alarmWithAbsoluteDate:fireDate]];
event.calendar = [eventSotre defaultCalendarForNewEvents];
NSError *err = nil;
if([eventSotre saveEvent:event span:EKSpanThisEvent error:&err]){
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"Event" message:@"Event added in calendar" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertview show];
}
else{
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"Event" message:[err description] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertview show];
}
Когда я запускаю этот код, я получаю сообщение «Событие добавлено в календарь». Две минуты дают мне достаточно времени, чтобы перейти к календарю и увидеть, что событие на самом деле было правильно спланировано. И выходи и жди, пока сработает мой будильник. И это делает.