美文网首页UIKitiOS进阶iOS 知识点
iOS10推送必看UNNotificationAttachmen

iOS10推送必看UNNotificationAttachmen

作者: 徐不同 | 来源:发表于2016-09-19 20:57 被阅读16213次

虽然这篇文章比较长,也不好理解,但是还是建议大家收藏,以后用到的时候,可以看看,有耐心的还是读一读。

这篇文章开始,我会跟大家好好讲讲,苹果新发布的iOS10的所有通知类。

一、创建本地通知事例详解:

注意啊,小伙伴们,本地通知也必须在appdelegate中注册中心,通知的开关打不打开无所谓的,毕竟是本地通知,但是通知的接收的代理,以及通知点击的代理,苹果给合二为一了。所以大家还是需要在appdelegate中写上这2个方法,还有不要忘记在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions注册通知中心。如果使用极光推送的小伙伴,写看一下我的基础篇,辛苦大家啦

创建一个UNNotificationRequest类的实例,一定要为它设置identifier, 在后面的查找,更新, 删除通知,这个标识是可以用来区分这个通知与其他通知
把request加到UNUserNotificationCenter, 并设置触发器,等待触发
如果另一个request具有和之前request相同的标识,不同的内容, 可以达到更新通知的目的

创建一个本地通知我们应该先创建一个UNNotificationRequest类,并且将这个类添加到UNUserNotificationCenter才可以。代码如下:

// 1.创建一个UNNotificationRequest
    NSString *requestIdentifer = @"TestRequest";
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifer content:content trigger:trigger];
    
// 2.将UNNotificationRequest类,添加进当前通知中心中
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {

    }];

在创建UNNotificationRequest类时,官方的解释是说,一个通知请求可以在预定通过时间和位置,来通知用户。触发的方式见UNNotificationTrigger的相关说明。调用该方法,在通知触发的时候。会取代具有相同标识符的通知请求,此外,消息个数受系统限制。

上面的翻译,看上去可能有些拗口,简单来说,就是我们需要为UNNotificationRequest设置一个标识符,通过标识符,我们可以对该通知进行添加,删除,更新等操作。

以下是完整的创建通知的代码:

    // 1.创建通知内容
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"徐不同测试通知";
    content.subtitle = @"测试通知";
    content.body = @"来自徐不同的简书";
    content.badge = @1;
    NSError *error = nil;
    NSString *path = [[NSBundle mainBundle] pathForResource:@"icon_certification_status1@2x" ofType:@"png"];
    // 2.设置通知附件内容
    UNNotificationAttachment *att = [UNNotificationAttachment attachmentWithIdentifier:@"att1" URL:[NSURL fileURLWithPath:path] options:nil error:&error];
    if (error) {
        NSLog(@"attachment error %@", error);
    }
    content.attachments = @[att];
    content.launchImageName = @"icon_certification_status1@2x";
    // 2.设置声音
    UNNotificationSound *sound = [UNNotificationSound defaultSound];
    content.sound = sound;

    // 3.触发模式
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];

    // 4.设置UNNotificationRequest
    NSString *requestIdentifer = @"TestRequest";
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifer content:content trigger:trigger1];
    
    //5.把通知加到UNUserNotificationCenter, 到指定触发点会被触发
    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
    }];

通过以上代码,我们就可以创建一个5秒触发本地通知,具体样式可以看下图


IMG_0123.PNG

根据上面内容,大家会发现在创建UNNotificationRequest的时候,会需要UNMutableNotificationContent以及UNTimeIntervalNotificationTrigger这两个类。下面我就对相关的类,以及类扩展,做相应的说明。

1.UNNotificationContent以及UNMutableNotificationContent(通知内容和可变通知内容)

通知内容分为可变的以及不可变的两种类型,类似于可变数组跟不可变数组。后续我们通过某一特定标识符更新通知,便是用可变通知了。
不管是可变通知还是不可变通知,都有以下的几个属性:

// 1.附件数组,存放UNNotificationAttachment类
@property (NS_NONATOMIC_IOSONLY, copy) NSArray <UNNotificationAttachment *> *attachments ;

// 2.应用程序角标,0或者不传,意味着角标消失
@property (NS_NONATOMIC_IOSONLY, copy, nullable) NSNumber *badge;

// 3.主体内容
@property (NS_NONATOMIC_IOSONLY, copy) NSString *body ;

// 4.app通知下拉预览时候展示的图
@property (NS_NONATOMIC_IOSONLY, copy) NSString *launchImageName;

// 5.UNNotificationSound类,可以设置默认声音,或者指定名称的声音
@property (NS_NONATOMIC_IOSONLY, copy, nullable) UNNotificationSound *sound ;

// 6.推送内容的子标题
@property (NS_NONATOMIC_IOSONLY, copy) NSString *subtitle ;

// 7.通知线程的标识
@property (NS_NONATOMIC_IOSONLY, copy) NSString *threadIdentifier;

// 8.推送内容的标题
@property (NS_NONATOMIC_IOSONLY, copy) NSString *title ;

// 9.远程通知推送内容
@property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *userInfo;

// 10.category标识
@property (NS_NONATOMIC_IOSONLY, copy) NSString *categoryIdentifier;

以上的的属性,我都增加了相应的说明,大家可以对照我的注释来使用。

2.UNNotificationAttachment (附件内容通知)

在UNNotificationContent类中,有个附件数组的属性,这就是包含UNNotificationAttachment类的数组了。

@property (NS_NONATOMIC_IOSONLY, copy) NSArray <UNNotificationAttachment *> *attachments ;

苹果的解释说,UNNotificationAttachment(附件通知)是指可以包含音频,图像或视频内容,并且可以将其内容显示出来的通知。使用本地通知时,可以在通知创建时,将附件加入即可。对于远程通知,则必须实现使用UNNotificationServiceExtension类通知服务扩展。

创建附件的方法是attachmentWithIdentifier:URL:options:error:。在使用时,必须指定使用文件附件的内容,并且文件格式必须是支持的类型之一。创建附件后,将其分配给内容对象的附件属性。 (对于远程通知,您必须从您的服务扩展做到这一点。)
附件通知支持的类型如下图:

QQ20160918-3.png-45.5kBQQ20160918-3.png-45.5kB

下面是创建UNNotificationAttachment的方法:

+ (nullable instancetype)attachmentWithIdentifier:(NSString *)identifier URL:(NSURL *)URL options:(nullable NSDictionary *)options error:(NSError *__nullable *__nullable)error;

注意:URL必须是一个有效的文件路径,不然会报错

这里我再在说下options的属性,一共有4种选项(这几个属性可研究死我了)

  • 1UNNotificationAttachmentOptionsTypeHintKey此键的值是一个包含描述文件的类型统一类型标识符(UTI)一个NSString。如果不提供该键,附件的文件扩展名来确定其类型,常用的类型标识符有
    kUTTypeImage,kUTTypeJPEG2000,kUTTypeTIFF,kUTTypePICT,kUTTypeGIF ,kUTTypePNG,kUTTypeQuickTimeImage等。看到这里你一定有疑问,这些类型导入报错了啊!!我研究了苹果文档,发现大家需要添加以下框架才可以,具体大家可以通过以下类型来处理。

注意:
框架就是#import<MobileCoreServices/MobileCoreServices.h>

使用方法如下:

dict[UNNotificationAttachmentOptionsTypeHintKey] = (__bridge id _Nullable)(kUTTypeImage);
  • 2UNNotificationAttachmentOptionsThumbnailHiddenKey,是一个BOOL值,为YES时候,缩略图将隐藏,默认为YES。如图:


    IMG_0124.PNG-67.2kBIMG_0124.PNG-67.2kB

    大家可以对照上面的图来看,就明白是哪里的图消失了。

使用方法如下:

    dict[UNNotificationAttachmentOptionsThumbnailHiddenKey] =  @YES;
  • 3UNNotificationAttachmentOptionsThumbnailClippingRectKey剪贴矩形的缩略图。这个密钥的值是包含一个归一化的CGRect - 也就是说,一个单元的矩形,其值是在以1.0〜 0.0 ,表示要显示的原始图像的所述部分的字典。例如,指定的(0.25 , 0.25)的原点和大小(0.5 ,0.5 )定义了剪辑矩形,只显示图像的中心部分。使用CGRectCreateDictionaryRepresentation函数来创建字典的矩形。
上面这句话是苹果的翻译,太绕口了。我简单说,就是我下面这幅图。 QQ20160919.png-728.4kBQQ20160919.png-728.4kB

整张图被分割了,整体比例为1,如果想得到图中阴影面积,就需要写的CGRect(0.5,0.5,0.25,0.25),意思是,从(0.5,0.5)为原点,面积为(0.25,0.25),大家可以理解成,即下面的方法。

使用方法如下:

    dict[UNNotificationAttachmentOptionsThumbnailClippingRectKey] = (__bridge id _Nullable)((CGRectCreateDictionaryRepresentation(CGRectMake(0.5, 0.5, 0.25 ,0.25))));;
使用上面的方法,可以得到一张图的阴影部分的图像,这张图像会是通知的缩略图。比如我下面的这个图,缩略图大家应该可以发现变了吧。 QQ20160919-10.png-49.2kBQQ20160919-10.png-49.2kB

这里为了理解,在给大家说几个"坐标点":
(0,0,0.25,0.25)左上角的最小正方形
(0,0,0.5,0.5) 四分之一的正方形,左上角
(0.5,0.5,0.5,0.5)四分之一的正方形,右下角
(0.5,0,0.5,0.5)四分之一的正方形,左下角
(0.25,0.25,0.5,0.5)最中心的正方形

特别注意:

调试到这里的时候,我感觉苹果应该是有个bug,就是我在来回变化这个显示缩略图的frame的时候,来回改,永远显示为第一次写的frame。我在修改UNNotificationRequest的requestIdentifer属性后,可以变换属性。所以我猜测可能相同requestIdentifer的通知,算一个通知,所以只能调用更新的方法,来变化缩略图的吃不腻吧,或许也不是bug。

  • 4UNNotificationAttachmentOptionsThumbnailTimeKey,一般影片附件会用到,指的是用影片中的某一秒来做这个缩略图;

使用方法如下:

    dict[UNNotificationAttachmentOptionsThumbnailTimeKey] =@10;

这里我们可以直接传递一个NSNumber的数值,比如使用影片第10s的画面来做缩略图就按照上面的来写。此外,要注意的是,这个秒数必须是这个影片长度范围内的,不然报错。

3.UNTimeIntervalNotificationTrigger (通知触发模式)

这个我在iOS开发 iOS10推送必看(基础篇)这篇文章中已经初步介绍了,现在我在详细介绍下。

  • 1.UNPushNotificationTrigger (远程通知触发)一般我们不会使用的

  • 2.UNTimeIntervalNotificationTrigger (本地通知) 一定时间之后,重复或者不重复推送通知。我们可以设置timeInterval(时间间隔)和repeats(是否重复)。

使用方法:

UNTimeIntervalNotificationTrigger *triggerOne = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];

解释:上面的方法是指5秒钟之后执行。repeats这个属性,如果需要为重复执行的,则TimeInterval必须大于60s,否则会报*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'time interval must be at least 60 if repeating'的错误!

  • 3.UNCalendarNotificationTrigger(本地通知) 一定日期之后,重复或者不重复推送通知 例如,你每天8点推送一个通知,只需要dateComponents为8。如果你想每天8点都推送这个通知,只要repeats为YES就可以了。
// 周一早上 8:00 上班
NSDateComponents *components = [[NSDateComponents alloc] init];
// 注意,weekday是从周日开始的,如果想设置为从周一开始,大家可以自己想想~
components.weekday = 2;
components.hour = 8;
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
  • 4.UNLocationNotificationTrigger (本地通知)地理位置的一种通知,使用这个通知,你需要导入
    #import<CoreLocation/CoreLocation.h>这个系统类库。示例代码如下:

//1、如果用户进入或者走出某个区域会调用下面两个方法
- (void)locationManager:(CLLocationManager *)manager
    didEnterRegion:(CLRegion *)region
- (void)locationManager:(CLLocationManager *)manager
    didExitRegion:(CLRegion *)region代理方法反馈相关信息

//2、一到某个经纬度就通知,判断包含某一点么
// 不建议使用!!!!!!CLRegion *region = [[CLRegion alloc] init];// 不建议使用!!!!!!


CLCircularRegion *circlarRegin = [[CLCircularRegion alloc] init];
[circlarRegin containsCoordinate:(CLLocationCoordinate2D)];

UNLocationNotificationTrigger *trigger4 = [UNLocationNotificationTrigger triggerWithRegion:circlarRegin repeats:NO];
 

注意,这里建议使用CLCircularRegion这个继承自CLRegion的类,因为我看到苹果已经飞起了CLRegion里面是否包含这一点的方法,并且推荐我们使用CLCircularRegion这个类型

如果你喜欢我的文章,不要忘记关注我,谢谢大家了~
另外如果你要转载,希望可以注明出处,我会写出更多更好的文章,来回馈大家~

稍后我会补充更多内容,敬请期待!!!

相关文章

网友评论

  • michaelxing:不知道楼主对,"不可消失的触发器有没有研究",就是iOS 10上的本地通知,左滑消失后,再出来一个相同的通知。通知不可消除的能力。
    程序员钙片吃多了:我来回答下吧,创建通知后,创建一个category,创建 category 时设置 UNNotificationCategoryOptionCustomDismissAction。然后点击消失后就会回调到代理里面,你可以再发一个一样的本地通知..不过这不是耍流氓么
    michaelxing:让通知永在,不让其消失
  • 单腿行走的大象:楼主 我怎么在这个推送扩展中 使用沙盒服务啊 我在这里进行的语音合成 保存到沙盒在播放 但是播放有问题
  • 小小云喵:小哥哥`有没有Swift版的教程呀
  • TianKengZhe:楼主,我非常气愤,什么叫「如果使用极光推送的小伙伴,写看一下我的基础篇,辛苦大家啦」,我们只是看看文章,还叫辛苦?谢谢你的分享,码字不易,更何况是技术文章,楼主辛苦了!
  • 田小北北:trigger1 是怎么通过编译的:flushed:
  • WebbWang0323:问下。repeat 时间大于60秒这个文档里面没有写。楼主怎么发现的?
  • 40efd9c90d53:您好,
    收到通知多了就会涉及到清除图片缓存的问题,但是我没法在宿主应用里访问到扩展的缓存文件(两个地方目录结构不一样),您碰到过这问题吗?
  • 农夫三全:您好,为什么我远程通知不走service里面的方法呢?
  • 杜员外:请问下。10之后的推送怎么去测试?就比如我UNTimeIntervalNotificationTrigger 设置了个1W 秒,完了我改手机本地时间是没有用的。我自己测试的话修改时间是没用,这个能有什么测试方法吗?
  • 阿兹尔:“UNNotificationAttachmentOptionsThumbnailHiddenKey,是一个BOOL值,为YES时候,缩略图将隐藏,默认为YES”,应该是Defaults to NO 这个在哪设置
  • Da雪山:楼主,请教下
    我在调试通知 UNNotificationServiceExtension 这个类中, 不执行这个方法啊,运行的是拓展的那个target啊
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
  • 许久__:有没有swift版的?
  • 863c73f31933:楼上,我这边在ios10上面推送为什么通知栏不显示
  • 海里的神秘骑士:UNNotificationAttachment 不太会用 能给一下设置附件的代码看看么
    徐不同:@海里的神秘骑士 参照下demo吧~
  • 洁简:content.launchImageName有什么用呢?写了也没有图片显示
  • aKerdi:楼主,为什么我设置timeinterval这个可以通知,但是设置为calendar这个触发器就没有任何反应呢?
  • fyf191:提醒时间如果要根据datePicker中的设置,应该用哪个方法??
  • 苹果开发爱好者:请问使用UNCalendarNotificationTrigger设置每周三10点提醒,如果今日刚好周三,我再九点的时候想主动取消今日10点的提醒,但是之后的每个周三10点还要继续提醒。这个如何实现🤓
  • abletyang:楼主请问一下 你这个有没有demo啊
    abletyang:@徐不同 嗯 其实刚评论 后面就发现了 谢谢感觉很有用啊
    徐不同:@abletyang :smile:有的,其他文章我都有讲:joy::joy:
  • coma:你好,想用UNCalendarNotificationTrigger每天发提醒,weekday应该怎么设?
  • JoshuaC:作者你好,不知道你有没有遇到这种情况,我在iOS 10.2下面是可以收到正常的图文推送的,但是在iOS 10.1.1的系统下却只能收到文字推送,不带图片,目前判断可能是没有走notification service的didReceiveNotificationRequest:withCompletionHandler:方法,因为在这个方法里面把title改了并没有生效,可能是什么原因导致的?
    徐不同:@JoshuaC 具体不详,说的太模糊了。我能猜的原因太多了:joy:
  • 3fda77b6cb66:你好,大神。 我最近要做一个本地通知的上下车提醒,用位置触发器并不触发通知,代码是按照您的写的,还有一个问题, 如果持续定位,程序在后台,通知是否还会触发。
    徐不同:@3fda77b6cb66 那个位置触发器,你需要改变经纬度的时候才会出发的,可以研究下region的那个类。:kissing_heart::kissing_heart:
  • Ko_Neko:LZ 求Demo
  • Z了个Y:赞:+1:🏻
  • x_tcan:“UNNotificationAttachmentOptionsThumbnailHiddenKey,是一个BOOL值,为YES时候,缩略图将隐藏,默认为YES”,应该是Defaults to NO
  • a245f043b546:按照你的步骤写了 iOS10 notification service extension 但是代理方法死活调用不到 用你的demo 发同样的通知 可以走到extension的方法去 我工程里面有什么设置导致extension没法调用么?求大神指导
  • _烩面_:在创建了notification service extension之后 用主工程的证书不行 要单独配个证书吗?
    JoshuaC:@DevShiLe 是重新创建证书还是描述文件?
  • antns丶:楼主,下拉放大展示的图片不是launchImageName吧 :sweat:
    34716bd593fa:我设置了 不是
  • linatan:想问下,有没有遇到过push中没有带图的情况,我这边测试会发现同一条push内容发送到客户端,偶尔会有一两条没有带图,很困惑,求教
    fengzilai:也碰到啦,怀疑是网络问题,有其他想法么?
  • seanward:有点疑问,你上面创建的各种通知,到底是下载AppDelegate文件里的那个方法里面的,希望讲解一些,谢谢。
  • linatan:通知里面的缩略图默认是 居中显示,如果用UNNotificationAttachmentOptionsThumbnailClippingRectKey,从原点(0,0)开始,面积 (1,1);也是显示不完整的,这是为什么啊,求解?
    徐不同:@linatan 对的,具体哪一块不确定。
    linatan:@徐不同 如果不写这个字典,默认展示的缩略图就是原大图的中间一块,难道这个字典是对这个已裁剪的图片进行操作的?
    徐不同:@linatan 你可以尝试不写这个字典,看图片是什么?那就是默认显示的图片啦
  • guitarJason:对您的文章分享表示感谢!受益很大~~~
    想请教一下您,您是如何学习这些新知识的呢?是通过看苹果的官方文档吗?
    zBk9cN:@guitarJason 官方文档,WWDC
  • 酷哥不回头看爆炸:这就是说现在注册本地通知,需要写两个版本了吗?10之前的和10之后的?
    neo63:@无言是非丶 三种,iOS8(不包括)以前的,iOS8-iOS10,iOS10(包括)以后的。
  • de9dc23fd8b6:注意邮件
    徐不同:@北京AK 没收到唉。。。😌
  • 谈Xx:你好 “- (void)locationManager:(CLLocationManager *)manager
    didEnterRegion:(CLRegion *)region
    - (void)locationManager:(CLLocationManager *)manager
    didExitRegion:(CLRegion *)region”
    这两个代理监听 是写在哪里的呢
    徐不同:嗯呐。不过不知道程序后台能不能用,一般用百度的,也没专门做过地域这个移动:joy:
    谈Xx:@徐不同 这个要应用活跃时吧,
    徐不同:@谈Xx 举个例子耶,比如你开启地图地位了,监听用户移动区域,也就是说程序运行期间支持定位,就有这个方法啦~~
  • linatan:想问下,附件中图片地址必须是https的么?
    linatan:@唐僧之妈 对的,厉害
    zBk9cN:开Allow Arbitrary Loads后可以使用HTTP
    徐不同:@linatan 不影响,之后我会上远程通知如何传附件的文章,敬请期待
  • 看看外面的世界:楼主, 我按照你做的 没有反应啊 通知
    看看外面的世界:@徐不同 需要设置什么东西?
    看看外面的世界:@徐不同 后来我又复制你的 代码 也是没有
    徐不同:@看看外面的世界 我本地通知,按照我代码写,写个几秒触发通知。肯定少东西啦
  • 3b73ac1e6515:不知有没有用xcode8打包上传过,使用xcode8打包上传成功了,但是构建版本一直刷不出来。博主是否遇到过这种情况
    3b73ac1e6515:@徐不同 我想应该是有点问题的,昨天都已经提交了,今天还是没有,而用xcode7提交之后,刷出来看到xcode8要不就是正在处理要不就是直接是失败
    徐不同:@cd_chen 耐心等等,苹果慢。。。
    徐不同:@cd_chen 打包已经提交了,无。。:smile:

本文标题:iOS10推送必看UNNotificationAttachmen

本文链接:https://www.haomeiwen.com/subject/wgqnettx.html