iOS本地推送简介

序言

推送消息是APP中重要的一个部分,它可以在用户不打开APP的情况下,告知用户一些APP内的消息,甚至是进行一些简易操作。推送一般分为两种,本地推送远程推送。本篇文章主要介绍本地推送。

UserNotification

在iOS10中,苹果升级了推送系统,使推送不仅仅能显示文字,还能够显示更多类型的信息,以及进行操作。因此,苹果废弃了UILocalNotification等API,而改用UserNotification来实现推送的功能。

让我们先来看看UserNotification都由哪些部分组成。


UserNotifications库目录概览

从上至下依次来解释一下这些文件的作用。

  • NSString+UserNotifications.h
    该文件是NSString的Category,提供了一个方法用来将文本信息进行本地化处理。

  • UNError.h
    该文件定义了一个枚举类UNErrorCode,用来标示不同种类的错误。

  • UNNotification.h
    这个类是推送的基础类。

  • UNNotificationAction.h
    这个类定义了推送通知中的交互操作。
    它还有个子类UNTextNotificationAction,负责定义推送通知中的文本框。

  • UNNotificationAttachment.h
    这个类定义了推送通知中的附件。

  • UNNotificationCategory.h
    这个类定义了推送通知的类别,与UNNotificationAction搭配使用。

  • UNNotificationContent.h
    这个类定义了推送通知中的内容。
    它还有个子类UNMutableNotificationContent,是可变版本。

  • UNNotificationRequest.h
    这个类是用来发起推送请求的

  • UNNotificationResponse.h
    这个类是在推送的回调中用来返回一些信息的。

  • UNNotificationServiceExtension.h
    这个类是在收到远程推送后更改推送内容再向用户展示的。

  • UNNotificationSettings.h
    这个类定义了推送通知的详细设置,例如声音、弹窗、红点等。

  • UNNotificationSound.h
    这个类定义了推送通知的声音。

  • UNNotificationTrigger.h
    这个类定义了推送通知的触发器。
    它有个子类UNPushNotificationTrigger,定义了基于远程推送的触发器。
    它有个子类UNTimeIntervalNotificationTrigger,定义了基于定时器的触发器。
    它有个子类UNCalendarNotificationTrigger,定义了基于日期的触发器。
    它有个子类UNLocationNotificationTrigger,定义了基于位置的触发器。

  • UNUserNotificationCenter.h
    这个类定义了管理中心,管理所有推送通知的行为。

  • UserNotifications.apinotes
    包含了这个模块的一些注释,主要是方便swift调用框架时的映射。

  • UserNotifications.h
    该文件引入了上述头文件,方便外界引用。

实际应用

1. 获取用户授权
[[UNUserNotificationCenter currentNotificationCenter]requestAuthorizationWithOptions:UNAuthorizationOptionAlert|
                                                                                     UNAuthorizationOptionSound|
                                                                                     UNAuthorizationOptionBadge|
                                                                                     UNAuthorizationOptionCarPlay
                                                                   completionHandler:^(BOOL granted, NSError * _Nullable error) {
        //granted代表用户是否同意授权。
}];

UNAuthorizationOptions的定义如下,每一条的作用已经标在注释里

typedef NS_OPTIONS(NSUInteger, UNAuthorizationOptions) {
    UNAuthorizationOptionBadge   = (1 << 0),//是否可以更新App的小红点
    UNAuthorizationOptionSound   = (1 << 1),//是否可以播放声音
    UNAuthorizationOptionAlert   = (1 << 2),//是否可以显示消息
    UNAuthorizationOptionCarPlay = (1 << 3),//是否可以在车载模式下推送
    UNAuthorizationOptionCriticalAlert __API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) = (1 << 4),//是否可以播放警告消息的声音
    UNAuthorizationOptionProvidesAppNotificationSettings __API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) = (1 << 5),//是否可以显示推送设置的按钮
    UNAuthorizationOptionProvisional __API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) = (1 << 6),//是否为临时授权,临时授权下用户可以在收到推送的时候设置授权
    UNAuthorizationOptionAnnouncement __API_AVAILABLE(ios(13.0), watchos(6.0)) __API_UNAVAILABLE(macos, tvos) = (1 << 7),//是否允许Siri自动播报
} __API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0), tvos(10.0));
2. 带文字的通知
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init];
content.title = [NSString localizedUserNotificationStringForKey:@"title" arguments:nil];
content.subtitle = [NSString localizedUserNotificationStringForKey:@"subtitle" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:@"body" arguments:nil];
    
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10.0 
                                                                                                repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"identifier" 
                                                                      content:content 
                                                                      trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter]addNotificationRequest:request 
                                                      withCompletionHandler:^(NSError * _Nullable error) {
        
}];

显示效果如下

预览
3. 带图片的通知

在原有代码上额外添加下面几行

NSString *path = [[NSBundle mainBundle]pathForResource:@"TestImage" ofType:@"png"];
NSURL *URL = [NSURL fileURLWithPath:path];
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"attachment"
                                                                                      URL:URL
                                                                                  options:nil
                                                                                    error:nil];
content.attachments = @[attachment];

显示效果如下

预览
预览(长按后)
4. 带视频的通知

和带图片的通知是一样的创建方式

NSString *path = [[NSBundle mainBundle]pathForResource:@"TestVideo" ofType:@"mov"];
NSURL *URL = [NSURL fileURLWithPath:path];
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"attachment"
                                                                                      URL:URL
                                                                                  options:nil
                                                                                    error:nil];
content.attachments = @[attachment];

显示效果如下

预览
5. 推送声音设置
content.sound = [UNNotificationSound soundNamed:@"sound.caf"];//自定义声音
//or
content.sound = [UNNotificationSound defaultSound];//默认声音
//or
content.sound = [UNNotificationSound defaultCriticalSound];//默认警告声
6. UNNotificationAction
UNNotificationAction * action = [UNNotificationAction actionWithIdentifier:@"action" 
                                                                     title:@"action" 
                                                                   options:UNNotificationActionOptionForeground];
NSArray *actionArr = @[action];
UNNotificationCategory * categoryNotification = [UNNotificationCategory categoryWithIdentifier:@"categoryOperationAction"
                                                                                       actions:actionArr
                                                                             intentIdentifiers:@[]
                                                                                       options:UNNotificationCategoryOptionCustomDismissAction];
NSSet *categories = [NSSet setWithObject:categoryNotification];
[[UNUserNotificationCenter currentNotificationCenter]setNotificationCategories:categories];
content.categoryIdentifier = @"categoryOperationAction";

其中UNNotificationAction定义的是一个按钮,动作,UNNotificationCategory则相当于一组Action的容器,方便管理。

UNNotificationActionOptions的定义如下。

typedef NS_OPTIONS(NSUInteger, UNNotificationActionOptions) {
    // 该操作是否只能在一个已解锁的设备上执行
    UNNotificationActionOptionAuthenticationRequired = (1 << 0),
    // 该操作是否是一个破坏性的操作,例如删除
    UNNotificationActionOptionDestructive = (1 << 1),
    // 该操作是否会导致APP进入前台
    UNNotificationActionOptionForeground = (1 << 2),
} __API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0)) __API_UNAVAILABLE(tvOS);

UNNotificationCategoryOptions的定义如下。

typedef NS_OPTIONS(NSUInteger, UNNotificationCategoryOptions) {
    // 是否要让Dismiss的操作也通过UNUserNotificationCenter的delegate回调
    UNNotificationCategoryOptionCustomDismissAction = (1 << 0),
    // 是否可以在车载模式中出现
    UNNotificationCategoryOptionAllowInCarPlay __API_UNAVAILABLE(macos) = (1 << 1),
    // 是否要显示标题,即使用户已经设置不可预览通知
    UNNotificationCategoryOptionHiddenPreviewsShowTitle __API_AVAILABLE(macos(10.14), ios(11.0)) __API_UNAVAILABLE(watchos, tvos) = (1 << 2),
    // 是否要显示副标题,即使用户已经设置不可预览通知
    UNNotificationCategoryOptionHiddenPreviewsShowSubtitle __API_AVAILABLE(macos(10.14), ios(11.0)) __API_UNAVAILABLE(watchos, tvos) = (1 << 3),
    // 是否允许Siri自动播报
    UNNotificationCategoryOptionAllowAnnouncement __API_AVAILABLE(ios(13.0), watchos(6.0)) __API_UNAVAILABLE(macos, tvos) = (1 << 4),
} __API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0)) __API_UNAVAILABLE(tvOS);

显示效果如下

预览
7. UNTextInputNotifactionAction
UNTextInputNotificationAction *action = [UNTextInputNotificationAction actionWithIdentifier:@"textAction"
                                                                                      title:@"textAction"
                                                                                    options:UNNotificationActionOptionNone
                                                                       textInputButtonTitle:@"send"
                                                                       textInputPlaceholder:@"placeholder"];

剩余代码与UNNotificationAction的一样。

点击后会显示输入框,显示效果如下


预览
8. Action回调

Action的回调是通过UNNotificationDelegate中的方法返回的

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void(^)(void))completionHandler {
    if ([response isKindOfClass:[UNTextInputNotificationResponse class]]) {
        UNTextInputNotificationResponse *textResponse = (UNTextInputNotificationResponse *)response;
        NSString *text = textResponse.userText;
        // text为用户输入的文本
    } else {
        if ([response.actionIdentifier isEqualToString:@"action"]) {
            // 此为标识符为action的操作
        }
    }
    completionHandler();
}

尾声

创建一个本地推送的基本流程就是这样,不过iOS上推送能做到的远不止如此。通过UserNotificationsUI库,开发者还可以自定义推送展开页面,限于篇幅,本篇文章就不作展开了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容