欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

本地通知使用总结

程序员文章站 2022-04-13 17:41:38
一.关于通知注册: ios8之前:registerforremotenotificationtypes: ios8之后:registerusernotificationsettings  ...

一.关于通知注册:

ios8之前:registerforremotenotificationtypes:

ios8之后:registerusernotificationsettings

 

二.关于提醒角标

1.本地推送uilocalnotification的applicationiconbadgenumber属性只会影响角标的显示,不会影响通知栏的通知处理。

1)当applicationiconbadgenumber>0时,角标会随applicationiconbadgenumber而变化。

2)当applicationiconbadgenumber=0时,角标维持推送前状态不变。

3)当applicationiconbadgenumber<0时,角标置0不显示。

2.远程推送的badge字段,只会影响角标的显示,不会影响通知栏的通知处理。

1)当badge>0时,角标会随badge而变化。

2)当badge=0时,角标维持不变。

3)当badge<0时,角标维持不变。

3.uiapplication的applicationiconbadgenumber属性既会影响角标的显示,又会影响通知栏通知的处理。

1)当applicationiconbadgenumber>0时,角标会随之变化,通知栏通知不变。

2)当applicationiconbadgenumber=0时,角标变为0不显示,通知栏通知清空。

3)当applicationiconbadgenumber<0时,角标变为0不显示,通知栏通知清空。

 

三.关于重复:

1. uilocalnotification.repeatinterval:repeatinterval的下限应该是nscalendarunitminute,即每分钟重复发送一次通知。如果设置为nscalendarunitsecond,那么消息不会重复,每秒发送一次通知,ios当然不会容许这样的存在了。这里比较不好的一点是nscalendarunit是个枚举类型,该值不能自定义,例如你不能塞个10.0给它从而希望它每十秒重复一次。所以如果你想每20分钟发送一次通知,一小时内发送3次,那么只能同时设定三个通知了。

2.若想设置复杂的重复通知,比如只在每周的周一、周三重复,则只能设置两个通知,分别进行周重复提醒。

 

四.关于userinfo:userinfo可以携带用户自定义的关于通知的信息,通常可以用来作为不同通知的区分标志

 

五.关于接收通知:

1. 如果此时应用程序还在运行(无论是在前台还是在后台)则会调用-(void)application:(uiapplication *)applicationdidreceivelocalnotification:(uilocalnotification *)notification(如果是远程通知则通过application:(uiapplication *)applicationdidreceivelocalnotification:(uilocalnotification *)notification)方法接收消息参数。参数中可以拿到notification对象,只要读取userinfo属性区分不同的通知即可。

2. 如果应用程序已经完全退出此时会调用- (bool)application:(uiapplication *)applicationdidfinishlaunchingwithoptions:(nsdictionary *)launchoptions方法:

1)通过点击通知栏通知进入:此时可以访问launchoptions中键为uiapplicationlaunchoptionslocalnotificationkey的对象,这个对象就是发送的通知,由此对象再去访问userinfo。

2)通过点击图标进入:可以通过[[uiapplication sharedapplication] scheduledlocalnotifications]获取全部的调度通知,并通过userinfo进行区分

 

六:关于覆盖安装:

如果我们的应用程序给系统发送的本地通知是周期性的,那么即使把程序删了重装,之前的本地通知在重装时依然存在,没有从系统中移除

 

 

 

#import "appdelegate.h"
#import "viewcontroller.h"
#import "homeviewcontroller.h"
#import "kcmainviewcontroller.h"

#define notificationid @"notificationid"
nsstring * const notificationcategoryident  = @"actionable";
nsstring * const notificationactiononeident = @"action_one";
nsstring * const notificationactiontwoident = @"action_two";


@implementation appdelegate

#pragma mark 用户打开app,分为点击图标打开与点击通知栏通知打开方式
- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions
{
    
    //程序开启时取消之前注册的通知
    //1.通过点击通知栏通知开启app
//    uilocalnotification *notification=[launchoptions objectforkey:uiapplicationlaunchoptionslocalnotificationkey];
//    if(notification!=nil){
//        nsdictionary *dic = [notification userinfo];
//        nsstring *identifer = [dic objectforkey:@"id"];
//        if ([identifer isequaltostring:notificationid]) {
//            [self cancellocation:notification];
//        }
//
//    }
//    
//    //2.通过点击图标开启app
//    else {
//        [self cancellocationwithidentifier:notificationid];
//    }
    
    [self cancellocationwithidentifier:notificationid];

    self.window = [[uiwindow alloc] initwithframe:[[uiscreen mainscreen] bounds]];
    
    viewcontroller *vc = [[viewcontroller alloc] init];
    self.window.rootviewcontroller = vc;
    
    self.window.backgroundcolor = [uicolor whitecolor];
    [self.window makekeyandvisible];
    
    
   
    uiusernotificationtype types = (uiusernotificationtypealert|
                                    uiusernotificationtypesound|
                                    uiusernotificationtypebadge);
    
    nsset *categories = [self addnotiactioncategories];
    
    
    //注册通知。ios8之后的方式
    if ([[uiapplication sharedapplication]currentusernotificationsettings].types!=uiusernotificationtypenone) {
        
    }else{
        [[uiapplication sharedapplication]registerusernotificationsettings:[uiusernotificationsettings settingsfortypes:types  categories:categories]];
        
    }
    return yes;
    
}

#pragma mark 调用过用户注册通知方法之后执行(也就是调用完registerusernotificationsettings:方法之后执行)
-(void)application:(uiapplication *)application didregisterusernotificationsettings:(uiusernotificationsettings *)notificationsettings{
    if (notificationsettings.types!=uiusernotificationtypenone) {
        
        [self addlocalnotification];
    }
}



#pragma mark 当应用在前台,或者后台运行时收到通知后的处理接口
-(void)application:(uiapplication *)application didreceivelocalnotification:(uilocalnotification *)notification{
    
    //获取通知的userinfo
    nsstring *receiveuseinfoid = notification.userinfo[@"id"];

        uialertcontroller *alertcontroller = [uialertcontroller alertcontrollerwithtitle:@"失败" message:@"失败" preferredstyle:uialertcontrollerstylealert];
    
        uialertaction *actcancel = [uialertaction actionwithtitle:@"取消" style:uialertactionstylecancel handler:^(uialertaction *action){
    
        }];
    
        uialertaction *actdetail = [uialertaction actionwithtitle:receiveuseinfoid style:uialertactionstyledefault handler:^(uialertaction *action){
    
        }];
    
        [alertcontroller addaction:actcancel];
        [alertcontroller addaction:actdetail];
        [[self getcurrentvc] presentviewcontroller:alertcontroller animated:yes completion:nil];
}


#pragma mark 当应用未在前台,收到本地通知后,左划通知,显示按钮对应的点击动作处理接口
- (void)application:(uiapplication *)application handleactionwithidentifier:(nullable nsstring *)identifier forlocalnotification:(uilocalnotification *)notification completionhandler:(void(^)())completionhandler {
    if ([identifier isequaltostring:notificationactiononeident]) {
        
        nslog(@"you chose action 1.");
    }
    else if ([identifier isequaltostring:notificationactiontwoident]) {
        
        nslog(@"you chose action 2.");
    }
    if (completionhandler) {
        
        completionhandler();
    }
}


#pragma mark 当应用未在前台,收到远程通知后,左划通知 通知滑动后的动作选项处理接口
- (void)application:(uiapplication *)application handleactionwithidentifier:(nsstring *)identifier forremotenotification:(nsdictionary *)userinfo completionhandler:(void (^)())completionhandler {
    
    if ([identifier isequaltostring:notificationactiononeident]) {
        
        nslog(@"you chose action 1.");
    }
    else if ([identifier isequaltostring:notificationactiontwoident]) {
        
        nslog(@"you chose action 2.");
    }
    if (completionhandler) {
        
        completionhandler();
    }
}


#pragma mark 进入前台后设置消息信息,只在由后台进入前台时调用,重新开启app时不会调用
-(void)applicationwillenterforeground:(uiapplication *)application{
//    nsinteger num =[uiapplication sharedapplication].applicationiconbadgenumber;
//    [[uiapplication sharedapplication]setapplicationiconbadgenumber:0];//进入前台取消应用消息图标
}

#pragma mark 进入前台后设置消息信息,由后台进入前台以及重新开启app时均会调用
- (void)applicationdidbecomeactive:(uiapplication *)application{

    [[uiapplication sharedapplication]setapplicationiconbadgenumber:0];//进入前台取消应用消息图标,同时清空通知栏通知

}

#pragma mark 程序即将退出时注册通知
-(void)applicationwillterminate:(uiapplication *)application{
    [self addlocalnotification];
}


#pragma mark - 私有方法
#pragma mark 添加本地通知

-(void)addlocalnotification{

    nsdate *firedate = [nsdate datewithtimeintervalsincenow:60 * 60 * 7];
    [self addnormallocationwithidentifier:notificationid withfiredate:firedate withrepeatinterval:nscalendarunitweekday];
}

//注册通知
-(void)addnormallocationwithidentifier:(nsstring *)identifier  withfiredate:(nsdate *)firedate withrepeatinterval:(nscalendarunit)repeatinterval{
    
    uilocalnotification *notification=[[uilocalnotification alloc]init];
    //设置调用时间
    notification.firedate=firedate;//通知触发的时间,10s以后
    notification.repeatinterval=repeatinterval ;//通知重复次数,枚举类型,除枚举类型外的其它值不会引起重复通知,为0时亦不会重复
    [notification setcategory:notificationcategoryident];
    //notification.repeatcalendar=[nscalendar currentcalendar];//当前日历,使用前最好设置时区等信息以便能够自动同步时间
    
    //设置通知属性
    notification.alertbody=@"你好你好,是否立即体验?"; //通知主体
    notification.applicationiconbadgenumber=4;//应用程序图标右上角显示的消息数
    notification.alertaction=@"打开应用"; //待机界面的滑动动作提示
    notification.alertlaunchimage=@"default";//通过点击通知打开应用时的启动图片,这里使用程序启动图片
    //notification.soundname=uilocalnotificationdefaultsoundname;//收到通知时播放的声音,默认消息声音
    notification.soundname=@"msg.caf";//通知声音(需要真机才能听到声音)
    
    //设置用户信息
    nsmutabledictionary *auserinfo = [[nsmutabledictionary alloc] init];
    auserinfo[@"id"] = identifier;
    auserinfo[@"sequence"] = [nsnumber numberwithint:-1];
    notification.userinfo = auserinfo;
    
    //按调度调用通知
    [[uiapplication sharedapplication] schedulelocalnotification:notification];

    //立即调用通知
    //[[uiapplication sharedapplication] presentlocalnotificationnow:notification];
}


//注册只在某些日期按周重复的通知
-(void)addrepeatlocationwithweekdate:(nsarray *)datearray withidentifier:(nsstring *)identifier{
    
    nsinteger todayweekday = [self weekdaywithdate:[nsdate date]];
    
    for (nsstring * datestr in datearray) {
         nsinteger datenum = [datestr integervalue];
        nsinteger dateseq;
        dateseq = (datenum + 7 -todayweekday)%7;
        if (!dateseq) {
            dateseq = 7;
        }
        
         nsdate *date = [[nsdate date] datebyaddingtimeinterval:(24*3600*dateseq)];
        [self addnormallocationwithidentifier:identifier withfiredate:date withrepeatinterval:nscalendarunitweekday];
    }
}

//注册有小睡nap分钟的通知
-(void)addnaplocationwithidentifier:(nsstring *)identifier  withfiredate:(nsdate *)firedate withrepeatinterval:(nscalendarunit)repeatinterval withnap:(nsinteger)nap{
    
    
    //若nap为0,则注册一次通知,相当于不重复,否则重复三次
    nsinteger times;
    if (nap > 0) {
        times = 3;
    } else {
        times = 1;
    }
    
    for (int i = 0; i < times; i++) {
        [self addnormallocationwithidentifier:identifier withfiredate:[firedate datebyaddingtimeinterval:i * nap * 60] withrepeatinterval:repeatinterval];
    }
}

#pragma mark 移除本地通知,在不需要此通知时记得移除


//移除指定通知
-(void)cancellocation:(uilocalnotification *)noti{
    [[uiapplication sharedapplication] cancellocalnotification:noti];
}


//移除特定id的通知
-(void)cancellocationwithidentifier:(nsstring *)identifier{
    
    for (uilocalnotification *noti in [[uiapplication sharedapplication] scheduledlocalnotifications]) {
        nsstring *notiid = noti.userinfo[@"id"];
        if ([notiid isequaltostring:identifier]) {
            
            [[uiapplication sharedapplication] cancellocalnotification:noti];
        }
    }
}

//移除全部通知
-(void)cancelalllocation{
    [[uiapplication sharedapplication] cancelalllocalnotifications];
}

#pragma mark 添加通知动作action
-(nsset *)addnotiactioncategories{
    uimutableusernotificationaction *action1;
    action1 = [[uimutableusernotificationaction alloc] init];
    [action1 setactivationmode:uiusernotificationactivationmodebackground];
    [action1 settitle:@"action 1"];
    [action1 setidentifier:notificationactiononeident];
    [action1 setdestructive:no];
    [action1 setauthenticationrequired:no];
    
    uimutableusernotificationaction *action2;
    action2 = [[uimutableusernotificationaction alloc] init];
    [action2 setactivationmode:uiusernotificationactivationmodebackground];
    [action2 settitle:@"action 2"];
    [action2 setidentifier:notificationactiontwoident];
    [action2 setdestructive:no];
    [action2 setauthenticationrequired:no];
    
    uimutableusernotificationcategory *actioncategory;
    actioncategory = [[uimutableusernotificationcategory alloc] init];
    [actioncategory setidentifier:notificationcategoryident];
    [actioncategory setactions:@[action1, action2]
                    forcontext:uiusernotificationactioncontextdefault];
    
    nsset *categories = [nsset setwithobject:actioncategory];
    return categories;
}


#pragma mark 返回周几
-(int)weekdaywithdate:(nsdate *)date{ //返回周几
    nscalendar *gregorian = [[nscalendar alloc]
                             initwithcalendaridentifier:nsgregoriancalendar];
    nsdatecomponents *components = [gregorian components:nscalendarunitweekday fromdate:date];
    int weekday = [components weekday];
    return weekday-1==0?7:weekday-1;
}

#pragma mark 获取窗口当前展示vc
- (uiviewcontroller *)getcurrentvc
{
    uiviewcontroller *result = nil;

    uiwindow * window = [[uiapplication sharedapplication] keywindow];
    if (window.windowlevel != uiwindowlevelnormal)
    {
        nsarray *windows = [[uiapplication sharedapplication] windows];
        for(uiwindow * tmpwin in windows)
        {
            if (tmpwin.windowlevel == uiwindowlevelnormal)
            {
                window = tmpwin;
                break;
            }
        }
    }

    uiview *frontview = [[window subviews] objectatindex:0];
    id nextresponder = [frontview nextresponder];

    if ([nextresponder iskindofclass:[uiviewcontroller class]])
        result = nextresponder;
    else
        result = window.rootviewcontroller;

    return result;
}

@end