Обновление номера значка iOS в режиме реального времени

Я создал собственный календарь для iOS, и я пытаюсь использовать номер значка, чтобы показать номер дня, но цифры не изменились после того, как прошел один день, я имею в виду, что они должны обновляться живо, вот мой код: мне нужно что-то вроде приложения Weather Live Это приложение не отправляет push-уведомления!

    int a = [DateComponents showDay];
    [UIApplication sharedApplication].applicationIconBadgeNumber = a ;

3 ответа

Решение

Это не легко сделать это в настоящее время в iOS. Вы можете подойти близко, но не обновлять значок каждый день, если только пользователь случайно не откроет приложение.

Вам нужно будет использовать UILocalNotification, Вы можете создать и запланировать "тихое" уведомление, которое обновляет значок приложения, не предупреждая пользователя или не воспроизводя звуковой сигнал, подобный следующему:

UILocalNotification* notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:seconds];
notification.timeZone = [NSTimeZone systemTimeZone];
notification.alertBody = nil;
notification.soundName = nil;
notification.applicationIconBadgeNumber = dayTomorrow;

[[UIApplication sharedApplication] scheduleLocalNotification:notification];
[notification release];

где dayTomorrow Int завтрашнего дня месяца. а также seconds некоторый интервал времени - это может быть что-то вроде интервала до полуночи. Когда это уведомление доставлено, для пользователя не будет никакого оповещения или звука, но значок приложения должен быть обновлен до нового значения. Вы можете сделать это уведомление повторяться каждый день, используя repeatInterval собственность, но проблема здесь в том, что на следующий день вам нужно изменить dayTomorrow чтобы быть другим значением, и снова на следующий день после этого. Но повторное предупреждение всегда будет иметь одинаковое значение в applicationIconBadgeNumber,

Поэтому я думаю, что единственный способ достичь чего-либо, близкого к тому, что вы хотите, - это запланировать несколько таких локальных уведомлений - вы можете запланировать до 64 заранее - каждый с интервалом в один день, и каждый со значением этого дня, установленным как applicationIconBadgeNumber, Они должны быть неповторяющимися, поэтому убедитесь, что вы установили repeatInterval в ноль (или не устанавливайте его, так как ноль является значением по умолчанию). Предполагая, что все эти уведомления надежно доставляются iOS, вы сможете обновить номер значка в автоматическом режиме и не беспокоить пользователя до 64 дней. После этого значок перестанет обновляться... если вам не удастся запланировать больше уведомлений в это время - т.е. когда пользователь откроет приложение. То, что вы можете попробовать сделать, это отменить все существующие запланированные уведомления при запуске приложения:

[[UIApplication sharedApplication] cancelAllLocalNotifications];

а затем выполните цикл за 64 дня, планируя уведомление на полночь каждый день с правильным днем ​​месяца для applicationIconBadgeNumber имущество. Пока пользователь запускает ваше приложение хотя бы раз в 64 дня, вы будете обновлять значок бейджа. Если вы планируете, чтобы пользователи вашего приложения открывали приложение часто (например, несколько раз в день), то оптимизация может заключаться в проверке количества существующих уведомлений, запланированных до их отмены, и создании 64 новых уведомлений, например:

if ([[[UIApplication sharedApplication] scheduledLocalNotifications] count] < 10)
{
    //there are 10 or fewer days' worth of notifications scheduled, so create and
    //schedule more here, up to 64 in total.
}

Еще пара моментов, на которые стоит обратить внимание:

  • Я не уверен, насколько надежны локальные уведомления. Push-уведомления не гарантируются, но я надеюсь и ожидаю, что локальные уведомления гарантированно будут доставлены. Например, если телефон выключен в полночь и включается только в 7 часов утра, я надеюсь, что местное уведомление, запланированное на полночь, будет доставлено немедленно. Но я никогда не проверял это.
  • Если ваше приложение в данный момент открыто при доставке запланированного уведомления, application:didReceiveLocalNotification: вызывается, но значок значка не будет обновлен. Поэтому, чтобы удовлетворить этот случай, я бы предложил обновлять значок значка до текущего дня каждый раз, когда приложение запускается (или возвращается на передний план из фона).
  • Не уверен, что Apple будет использовать этот значок значка. При просмотре вашего приложения они могут почувствовать, что оно вводит пользователя в заблуждение, поскольку оно обычно используется для указания количества элементов новых / измененных данных в приложении. Так что ваше приложение может быть отклонено за это.
  • В идеале Apple должна предоставить API для разработчиков, чтобы предоставить пользователю такую ​​"краткую" информацию, независимо от того, достигается ли это каким-либо образом путем изменения значка / значка приложения или с помощью виджета и т. Д. работать, но, очевидно, немного обидно, чтобы обойти текущие ограничения iOS. Встроенное приложение календаря меняет свой значок каждый день, чтобы показать день месяца, и я вижу, что многие приложения могут извлечь выгоду из этого поведения - например, приложение погоды может отображать значок погодных условий в текущем местоположении.

РЕДАКТИРОВАТЬ:

Вот фрагмент кода, чтобы отменить любые существующие локальные уведомления и запланировать 64 на будущее в полночь и с правильным днем ​​месяца, указанным в качестве номера значка:

[[UIApplication sharedApplication] cancelAllLocalNotifications];

NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]];

[components setHour:0];
[components setMinute:0];
[components setSecond:0];

NSDate* midnightToday = [calendar dateFromComponents:components];

const int SECONDS_PER_DAY = 60 * 60 * 24;

for (int i = 1; i <= 64; i++)
{
    NSDate* futureDate = [midnightToday dateByAddingTimeInterval:i * SECONDS_PER_DAY];
    NSDateComponents* components = [calendar components:NSDayCalendarUnit fromDate:futureDate];

    UILocalNotification* notification = [[UILocalNotification alloc] init];
    notification.fireDate = futureDate;
    notification.timeZone = [NSTimeZone systemTimeZone];
    notification.alertBody = nil;
    notification.soundName = nil;
    notification.applicationIconBadgeNumber = components.day;

    //NSLog(@"futureDate: %@", [NSDateFormatter localizedStringFromDate:futureDate dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle]);
    //NSLog(@"notification: %@", notification);        

    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    [notification release];
}

[calendar release];

Что здесь происходит:

  • Мы берем сегодняшнюю дату с [NSDate date] и затем разбейте его на компоненты, которые мы хотим сохранить (год, месяц, день), а затем установите компоненты времени (часы, минуты, секунды) равными полуночи. Это дает нам midnightToday,
  • Мы перебираем 64 раза, каждый раз создавая новую дату, от 1 до 64 дней в будущем, принимая midnightToday и добавление количества секунд в день, умноженного на то, сколько дней в будущем мы хотим, чтобы дата была. Мы используем эту дату, чтобы запланировать местное уведомление.
  • Нам также нужно определить день месяца для номера значка. Итак, снова мы используем NSDateComponents разбить будущую дату на интересующие нас компоненты - в данном случае это только день, поэтому мы указываем NSDayCalendarUnit, Затем мы можем установить applicationIconBadgeNumber быть components.day
  • Каждое из 64 уведомлений планируется с помощью приложения UIApplication, которое должно быть доставлено в течение от 1 до 64 дней.

Обратите внимание, что это, вероятно, будет работать только для пользователей, которые используют григорианский календарь (в западном стиле) - в зависимости от вашего рынка вам может понадобиться рассмотреть другие типы календарей, используемые по всему миру, и поддерживать их тоже.

Вы должны быть в состоянии сделать это с UILocalNotification

Я не уверен, что вы можете установить автоматическое повторение один раз в день, но вы можете спамить уведомления, чтобы имитировать это.

http://developer.apple.com/library/IOs/#documentation/iPhone/Reference/UILocalNotification_Class/Reference/Reference.html

Как и где вы вызываете этот метод? Если вы установите таймер для запуска этого кода каждые x секунд, он будет обновляться при следующем срабатывании таймера.

Другие вопросы по тегам