В настоящее время это нелегко сделать в 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. Встроенное приложение календаря меняет свой значок каждый день, чтобы показать день месяца, и я вижу, что многие приложения могут извлечь выгоду из этого поведения, например приложение погоды может отображать значок погодных условий в текущем местоположении.
EDIT:
Вот фрагмент кода для отмены любых существующих локальных уведомлений и расписания 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 дня.что это, вероятно, будет работать только для пользователей, которые используют григорианский календарь (в западном стиле) - в зависимости от вашего рынка вам может понадобиться рассмотреть другие типы календарей, используемые по всему миру, и поддерживать их тоже.