2012-01-04 108 views
13

我爲iOS創建了一個自定義日曆,並且我嘗試使用徽章號碼來顯示當天的號碼,但是號碼在一天過後沒有更改,我的意思是他們應該更新活潑,這裏是我的代碼:我需要類似天氣直播的應用程序,這個應用程序不會發送任何推送通知!iOS徽章號碼實時更新

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

儘管人們可以通過設置禁用通知,但您的確意識到了這一點。 – 2012-05-19 19:26:44

回答

31

這是不容易在目前的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設置爲零(或不要設置它,因爲nil是默認值)。假設所有這些通知都可以通過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. 
} 

幾個其他點要注意:

  • 我不確定本地通知的可靠程度。無法保證推送通知,但我希望並期望本地通知能夠保證提供。例如如果電話在午夜關閉,並且只在上午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天內交付。

請注意,這可能只適用於使用格里曆(西式)日曆的用戶 - 根據您的市場,您可能需要考慮世界各地正在使用的其他日曆類型並支持這些日曆類型。

+0

非常感謝Rob幫助我,但明天SECONDS_PER_DAY會顯示,後天會顯示I * SECONDS_PER_DAY,我將它改爲:60 * 60;並刪除'我*'因爲我的日曆是波斯日曆,所以我在等待明天看到更新徽章號碼 – 2012-05-15 08:22:45

+0

,當然點擊獎勵這個賞金;) – 2012-05-15 08:23:12

+1

謝謝,抱歉它是一個很大的文本牆 - 我對這個問題非常感興趣,必須找到解決辦法!在調試器中查看'futureDate'時,要小心,因爲我認爲它總是顯示爲GMT而不是您自己的時區。但是,如果您在設置'fireDate'後檢查通知,它會顯示爲您時區中的正確時間。所以一定要檢查一下。我也已經將它安裝在我的設備上,耐心等待,直到明天,看看它是否全部正確更新:) – 2012-05-15 08:50:23

2

如何以及在哪裏調用此方法?如果您設置一個計時器以每x秒運行一次此代碼,它將在下一次計時器火災時更新。

+0

如果您退出應用程序,計時器將不會運行 – oskob 2012-01-04 21:28:52

+1

您可以發送一個UILocalNotification在午夜重啓,間隔時間爲NSDayCalendarUnit。並在AppDelegate中更新徽章: - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification。 – 2012-01-04 21:41:29