天天看點

iOS監聽模式系列之本地通知Notification本地通知

本地通知

本地通知是由本地應用觸發的,它是基于時間行為的一種通知形式,例如鬧鐘定時、待辦事項提醒,又或者一個應用在一段時候後不使用通常會提示使用者使用此應用等都是本地通知。建立一個本地通知通常分為以下幾個步驟:

  1. 建立UILocalNotification。
  2. 設定處理通知的時間fireDate。
  3. 配置通知的内容:通知主體、通知聲音、圖示數字等。
  4. 配置通知傳遞的自定義資料參數userInfo(這一步可選)。
  5. 調用通知,可以使用scheduleLocalNotification:按計劃排程一個通知,也可以使用presentLocalNotificationNow立即調用通知。

下面就以一個程式更新後使用者長期沒有使用的提醒為例對本地通知做一個簡單的了解。在這個過程中并沒有牽扯太多的界面操作,所有的邏輯都在AppDelegate中:進入應用後如果沒有注冊通知,需要首先注冊通知請求使用者允許通知;一旦調用完注冊方法,無論使用者是否選擇允許通知此刻都會調用應用程式的- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings代理方法,在這個方法中根據使用者的選擇:如果是允許通知則會按照前面的步驟建立通知并在一定時間後執行。

AppDelegate.m

#import "AppDelegate.h"
#import "KCMainViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

#pragma mark - 應用代理方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    _window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    
    _window.backgroundColor =[UIColor colorWithRed:249/255.0 green:249/255.0 blue:249/255.0 alpha:1];
    
    //設定全局導覽列風格和顔色
    [[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1]];
    [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
    
    KCMainViewController *mainController=[[KCMainViewController alloc]init];
    _window.rootViewController=mainController;
    
    [_window makeKeyAndVisible];

    //如果已經獲得發送通知的授權則建立本地通知,否則請求授權(注意:如果不請求授權在設定中是沒有對應的通知設定項的,也就是說如果從來沒有發送過請求,
即使通過設定也打不開消息允許設定)
    if ([[UIApplication sharedApplication]currentUserNotificationSettings].types!=UIUserNotificationTypeNone) {
        [self addLocalNotification];
    }else{
        [[UIApplication sharedApplication]registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:
UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound  categories:nil]];
    }
    
    return YES;
}

#pragma mark 調用過使用者注冊通知方法之後執行(也就是調用完registerUserNotificationSettings:方法之後執行)
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)
notificationSettings{
    if (notificationSettings.types!=UIUserNotificationTypeNone) {
        [self addLocalNotification];
    }
}

#pragma mark 進入前台後設定消息資訊
-(void)applicationWillEnterForeground:(UIApplication *)application{
    [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];//進入前台取消應用消息圖示
}

#pragma mark - 私有方法
#pragma mark 添加本地通知
-(void)addLocalNotification{
    
    //定義本地通知對象
    UILocalNotification *notification=[[UILocalNotification alloc]init];
    //設定調用時間
    notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:10.0];//通知觸發的時間,10s以後
    notification.repeatInterval=2;//通知重複次數
    //notification.repeatCalendar=[NSCalendar currentCalendar];//目前月曆,使用前最好設定時區等資訊以便能夠自動同步時間
    
    //設定通知屬性
    [email protected]"最近添加了諸多有趣的特性,是否立即體驗?"; //通知主體
    notification.applicationIconBadgeNumber=1;//應用程式圖示右上角顯示的消息數
    [email protected]"打開應用"; //待機界面的滑動動作提示
    [email protected]"Default";//通過點選通知打開應用時的啟動圖檔,這裡使用程式啟動圖檔
    //notification.soundName=UILocalNotificationDefaultSoundName;//收到通知時播放的聲音,預設消息聲音
    [email protected]"msg.caf";//通知聲音(需要真機才能聽到聲音)
    
    //設定使用者資訊
    [email protected]{@"id":@1,@"user":@"Kenshin Cui"};//綁定到通知上的其他附加資訊
    
    //調用通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}

#pragma mark 移除本地通知,在不需要此通知時記得移除
-(void)removeNotification{
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
}
@end      

請求獲得使用者允許通知的效果:

iOS監聽模式系列之本地通知Notification本地通知

注意:

  • 在使用通知之前必須注冊通知類型,如果使用者不允許應用程式發送通知,則以後就無法發送通知,除非使用者手動到iOS設定中打開通知。
  • 本地通知是有作業系統統一排程的,隻有在應用退出到背景或者關閉才能收到通知。(注意:這一點對于後面的推送通知也是完全适用的。 )
  • 通知的聲音是由iOS系統播放的,格式必須是Linear PCM、MA4(IMA/ADPCM)、µLaw、aLaw中的一種,并且播放時間必須在30s内,否則将被系統聲音替換,同時自定義聲音檔案必須放到main boundle中。
  • 本地通知的數量是有限制的,最近的本地通知最多隻能有64個,超過這個數量将被系統忽略。
  • 如果想要移除本地通知可以調用UIApplication的cancelLocalNotification:或cancelAllLocalNotifications移除指定通知或所有通知。

從上面的程式可以看到userInfo這個屬性我們設定了參數,那麼這個參數如何接收呢?

在iOS中如果點選一個彈出通知(或者鎖屏界面滑動檢視通知),預設會自動打開目前應用。由于通知由系統排程那麼此時進入應用有兩種情況:如果應用程式已經完全退出那麼此時會調用- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法;如果此時應用程式還在運作(無論是在前台還是在背景)則會調用-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification方法接收消息參數。當然如果是後者自然不必多說,因為參數中已經可以拿到notification對象,隻要讀取userInfo屬性即可。如果是前者的話則可以通路launchOptions中鍵為UIApplicationLaunchOptionsLocalNotificationKey的對象,這個對象就是發送的通知,由此對象再去通路userInfo。為了示範這個過程在下面的程式中将userInfo的内容寫入檔案以便模拟關閉程式後再通過點選通知打開應用擷取userInfo的過程。

AppDelegate.m

#import "AppDelegate.h"
#import "KCMainViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

#pragma mark - 應用代理方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    _window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    
    _window.backgroundColor =[UIColor colorWithRed:249/255.0 green:249/255.0 blue:249/255.0 alpha:1];
    
    //設定全局導覽列風格和顔色
    [[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1]];
    [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
    
    KCMainViewController *mainController=[[KCMainViewController alloc]init];
    _window.rootViewController=mainController;
    
    [_window makeKeyAndVisible];

    //添加通知
    [self addLocalNotification];

    //接收通知參數
    UILocalNotification *notification=[launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    NSDictionary *userInfo= notification.userInfo;
    
    [userInfo writeToFile:@"/Users/kenshincui/Desktop/didFinishLaunchingWithOptions.txt" atomically:YES];
    NSLog(@"didFinishLaunchingWithOptions:The userInfo is %@.",userInfo);
    
    return YES;
}

#pragma mark 接收本地通知時觸發
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
    NSDictionary *userInfo=notification.userInfo;
    [userInfo writeToFile:@"/Users/kenshincui/Desktop/didReceiveLocalNotification.txt" atomically:YES];
    NSLog(@"didReceiveLocalNotification:The userInfo is %@",userInfo);
}

#pragma mark 調用過使用者注冊通知方法之後執行(也就是調用完registerUserNotificationSettings:方法之後執行)
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)
notificationSettings{
    if (notificationSettings.types!=UIUserNotificationTypeNone) {
        [self addLocalNotification];
    }
}

#pragma mark 進入前台後設定消息資訊
-(void)applicationWillEnterForeground:(UIApplication *)application{
    [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];//進入前台取消應用消息圖示
}

#pragma mark - 私有方法
#pragma mark 添加本地通知
-(void)addLocalNotification{
    
    //定義本地通知對象
    UILocalNotification *notification=[[UILocalNotification alloc]init];
    //設定調用時間
    notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:10.0];//通知觸發的時間,10s以後
    notification.repeatInterval=2;//通知重複次數
    //notification.repeatCalendar=[NSCalendar currentCalendar];//目前月曆,使用前最好設定時區等資訊以便能夠自動同步時間
    
    //設定通知屬性
    [email protected]"最近添加了諸多有趣的特性,是否立即體驗?"; //通知主體
    notification.applicationIconBadgeNumber=1;//應用程式圖示右上角顯示的消息數
    [email protected]"打開應用"; //待機界面的滑動動作提示
    [email protected]"Default";//通過點選通知打開應用時的啟動圖檔
    //notification.soundName=UILocalNotificationDefaultSoundName;//收到通知時播放的聲音,預設消息聲音
    [email protected]"msg.caf";//通知聲音(需要真機)
    
    //設定使用者資訊
    [email protected]{@"id":@1,@"user":@"Kenshin Cui"};//綁定到通知上的其他額外資訊
    
    //調用通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
@end      

上面的程式可以分為兩種情況去運作:一種是啟動程式關閉程式,等到接收到通知之後點選通知重新進入程式;另一種是啟動程式後,進入背景(其實在前台也可以,但是為了明顯的體驗這個過程建議進入背景),接收到通知後點選通知進入應用。另種情況會分别按照前面說的情況調用不同的方法接收到userInfo寫入本地檔案系統。有了userInfo一般來說就可以根據這個資訊進行一些處理,例如可以根據不同的參數資訊導航到不同的界面,假設是更新的通知則可以導航到更新内容界面等。

繼續閱讀