iOS10推送必看UNNotificationContentEx

作者: 徐不同 | 来源:发表于2016-10-14 16:17 被阅读7644次

    大伙久等啦~这绝对是最全最详细的 UNNotificationContentExtension讲解哟~

    这篇文章中,我会给大家补充完推送内容的后续部分,希望大家看完这篇文章后,便可以轻松的玩转推送了。

    1、UNNotificationContentExtension

    1.1、UNNotificationContentExtension简介

    简单来说,UNNotificationContentExtension这个类,也是iOS10推送的新特性,官方文档用这么一句话,简单的解释了一下,Presents a custom interface for a delivered local or remote notification.(当你收到远程或者本地通知的时候,弹出一个自定义界面)。效果如下图所示

    image

    第二步:选择创建类型


    QQ20161014-1.png-82.6kBQQ20161014-1.png-82.6kB

    之后便可以看到生成了这些内容


    QQ20161014-2.png-22.2kBQQ20161014-2.png-22.2kB

    1.3、如何使用以及相关Demo

    说到如何使用这个类,我们就一定要先说一下,系统帮我们生成的这几个文件分别代表了什么意思。


    QQ20161014-2.png-22.2kBQQ20161014-2.png-22.2kB

    >0.Info.plist

    QQ20161014-3.png-102.4kBQQ20161014-3.png-102.4kB

    在这个NSExtensionAttributes的字典下面,我们有三个属性可以添加
    一.UNNotificationExtensionCategory.
    (必须要有,系统已经创建好)
    解释:对应这个key的值,可以是一个字符串,也可以是一个数组,每一个字符串都是一个identifier,这个identifier对应着每一个UNMutableNotificationContent的categoryIdentifier的属性。

    简单来说,就是在收到通知的时候,我们可以让服务器把这个通知的categoryIdentifier带上,作用是,我们可以根据视频,音乐,图片,来分别自定义我们的通知内容。不同的分类标识符,也会在我们讲到UNNotificationAction的时候,帮助我们区分是什么类型的通知,方便我们对不同类型的通知做出不同的操作行为。上面的截图中,我是一个字符串的形式。下图为数组形式:


    QQ20161014-4.png-39.9kBQQ20161014-4.png-39.9kB

    使用的时候,我们参照如下代码:

    // 1.这个方法是UNNotificationServiceExtension类里面的方法,可以参照我上一篇文章讲的UNNotificationServiceExtension,我要在这里重写我的通知。
    
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
        // copy发来的通知,开始做一些处理
        self.bestAttemptContent = [request.content mutableCopy];
        // Modify the notification content here...
        self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
        // 重写一些东西
        self.bestAttemptContent.title = @"我是标题";
        self.bestAttemptContent.subtitle = @"我是子标题";
        self.bestAttemptContent.body = @"来自徐不同";
        // 附件
        NSDictionary *dict =  self.bestAttemptContent.userInfo;
        NSDictionary *notiDict = dict[@"aps"];
        NSString *imgUrl = [NSString stringWithFormat:@"%@",notiDict[@"imageAbsoluteString"]];
       
        !!!!! 这里是重点!!!!!!!!!!!!
        // 我在这里写死了category1,其实在收到系统推送时,每一个推送内容最好带上一个catagory,跟服务器约定好了,这样方便我们根据categoryIdentifier来自定义不同类型的视图,以及action
         self.bestAttemptContent.categoryIdentifier = @"category1";
        
    
    
    }
    
    

    大家注意上面的

     !!!!! 这里是重点!!!!!!!!!!!!
        // 我在这里写死了category1,其实在收到系统推送时,每一个推送内容最好带上一个catagory,跟服务器约定好了,这样方便我们根据categoryIdentifier来自定义不同类型的视图,以及action
         self.bestAttemptContent.categoryIdentifier = @"category1";
    

    这里设置categoryIdentifier,最好让服务器的推送内容带上这个,然后我们好更加的定制化。不建议本地写死。
    具体可以参考我的demo地址

    二.UNNotificationExtensionInitialContentSizeRatio.
    (必须要有,系统已经创建好)
    解释:这个值的类型是一个浮点类型,代表的是高度与宽度的比值。系统会使用这个比值,作为初始化view的大小。举个简单的例子来说,如果该值为1,则该视图为正方形。如果为0.5,则代表高度是宽度的一半。

    注意这个值只是初始化的一个值,在这个扩展添加后,可以重写frame,展示的时候,在我们还没打开这个视图预览时,背景是个类似图片占位的灰色,那个灰色的高度宽度之比,就是通过这个值来设定。

    三.UNNotificationExtensionDefaultContentHidden.
    (可选)
    解释:这个值是一个BOOL值,当为YES时,会隐藏上方原本推送的内容视图,只会显示我们自定义的视图。(因为在自定义视图的时候,我们可以取得推送内容,然后按照我们想要的布局,展示出来)如果为NO时(默认为NO),推送视图就会既有我们的自定义视图,也会有系统原本的推送内容视图(这里附件是不会显示的,只会显示body里面的文字哟)

    四.至于NSExtensionMainStoryboard以及NSExtensionPointIdentifier,系统默认生成,大家直接用就好,如果需要更改的,只能更改使用的storyboard的名字(不过应该没人会把系统的删除在建立一个吧 O(∩_∩)O)

    >1.MainInterface.storyboard

    这个就是个简单的storyboard文件,内部有一个View,这个View就是在上面的图层中的自定义View视图了。它与NotificationViewController所绑定。

    >2.NotificationViewController

    这是是系统帮我们默认创建了一个控制器,继承UIViewController,其实就是一个控制器啦。
    说道这个控制器我们需要讲解一个方法:

    1. 遵守UNNotificationContentExtension的协议,我们需要用到一下的方法
    // 这个方法是说,只要你收到通知,并且保证categoryIdentifier的设置,跟info.plist里面设置的一样,你就会调用这个方法。注意:一个会话的多个通知,每个通知收到时,都可以调用这个方法。
    - (void)didReceiveNotification:(UNNotification *)notification;
    

    使用如下:

    - (void)didReceiveNotification:(UNNotification *)notification {
        这个方法,可以给自己的控件赋值啊,调整frame啊等等,我在这里打印出来了通知的内容,供大家使用。
        NSDictionary *dict =  notification.request.content.userInfo;
        // 这里可以把打印的所有东西拿出来
        NSLog(@"%@",dict);
        
        /****************************打印的信息是************
        aps =     {
            alert = "This is some fancy message.";
            badge = 1;
            from = "大家好,我是徐不同";
            imageAbsoluteString = "http://upload.univs.cn/2012/0104/1325645511371.jpg";
            "mutable-content" = 1;
            sound = default;
        };
    }
        *******************************************/
    
    }
    
    

    说到这里,简单的UNNotificationContentExtension已经说完了,我在给大家补充一点。在UNNotificationContentExtension.h中,有着这么一个枚举

    typedef NS_ENUM(NSUInteger, UNNotificationContentExtensionMediaPlayPauseButtonType) {  
        // 没有播放按钮
        UNNotificationContentExtensionMediaPlayPauseButtonTypeNone,
        // 有播放按钮,点击播放之后,按钮依旧存在,类似音乐播放的开关
        UNNotificationContentExtensionMediaPlayPauseButtonTypeDefault,
        // 有播放按钮,点击后,播放按钮消失,再次点击暂停播放后,按钮恢复
        UNNotificationContentExtensionMediaPlayPauseButtonTypeOverlay,
    }
    

    看到这么枚举,大家一定纳闷怎么使用啊。请看下面的几个属性

    // 设置播放按钮的属性
    @property (nonatomic, readonly, assign) UNNotificationContentExtensionMediaPlayPauseButtonType mediaPlayPauseButtonType;
    // 设置播放按钮的frame
    @property (nonatomic, readonly, assign) CGRect mediaPlayPauseButtonFrame;
    // 设置播放按钮的颜色
    @property (nonatomic, readonly, copy) UIColor *mediaPlayPauseButtonTintColor;
    // 开始跟暂停播放
    - (void)mediaPlay;
    - (void)mediaPause;
    

    还有以下的类,这个类虽然也有开始播放跟结束播放的方法,不过要注意,这个是属于NSExtensionContext的,而上面我们讲的方法是UNNotificationContentExtension协议方法里的。大家要注意。

    
    @interface NSExtensionContext (UNNotificationContentExtension)
    // 控制播放
    - (void)mediaPlayingStarted  
    // 控制暂停
    - (void)mediaPlayingPaused 
    @end
    

    看到这些属性,想要知道如何使用,请看我下面的步骤:

    分析:
    首先这些属性都是readonly的,所以直接用self.属性去修改肯定是报错的,所以我们能用的就只有get方法了。
    其次:根据button的类型,我们可以联想到,如果button没有,这个播放开始暂停的方法也没用了。如果有button,自然我们就有了播放的操作,联想别的UI空间,我们得出了一定要重写它的frame,来确定他的位置。设置颜色,来设置它的显示颜色。设置button的类型,让他显示出来。

    // 返回默认样式的button
    - (UNNotificationContentExtensionMediaPlayPauseButtonType)mediaPlayPauseButtonType
    {   
        return UNNotificationContentExtensionMediaPlayPauseButtonTypeDefault;
    }
    // 返回button的frame
    - (CGRect)mediaPlayPauseButtonFrame
    {   
        return CGRectMake(100, 100, 100, 100);
    }
    // 返回button的颜色
    - (UIColor *)mediaPlayPauseButtonTintColor{
        return [UIColor blueColor];
    }
    

    通过上面的代码,我们的button已经可以显示出来了。如下图(请忽略下面的策略等按钮):


    IMG_2475.PNG-115.4kBIMG_2475.PNG-115.4kB

    具体位置,大家可以通过重写frame来确定button的位置。

    当我们点击这个蓝色button的时候,便可以执行一些播放暂停操作了,如下

    - (void)mediaPlay{
        NSLog(@"mediaPlay,开始播放");
      
    }
    - (void)mediaPause{
        NSLog(@"mediaPause,暂停播放");
       
    }
    

    说道这里,还少说一个地方,那就是NSExtensionContext类的播放暂停事件我们需要什么时候调用呢?
    经过我的研究,可以这么使用,如下

    - (void)mediaPlay{
        NSLog(@"mediaPlay,开始播放");
        // 点击播放按钮后,4s后暂停播放
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self.extensionContext mediaPlayingPaused];
        });
    }
    - (void)mediaPause{
        NSLog(@"mediaPause,暂停播放");
        // 点击暂停按钮,10s后开始播放
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self.extensionContext mediaPlayingStarted];
        });
    }
    

    这里需要说几个注意点
    1.在这个控制器中,我们可以直接电泳self.extensionContext,来调用它的播放暂停方法。
    2.调用这个播放暂停方法,并不会重新调用- (void)mediaPlay{}或者- (void)mediaPause{},只能单纯的调用。经过我的测试,

    - (void)mediaPlayingStarted{
        NSLog(@"主动调用开始的方法");
    }
    - (void)mediaPlayingPaused
    {
        NSLog(@"主动调用暂停的方法");
    }
    

    用上述代码,是监听不到方法点击的哟~

    有了自定义内容,自然也就有了自定义的action(行为),我明日补上谢谢大家咯
    如果你喜欢我的文章,不要忘记关注我,谢谢大家了~
    另外如果你要转载,希望可以注明出处,我会写出更多更好的文章,来回馈大家~

    重要的事情说三遍,demo地址
    重要的事情说三遍,demo地址
    重要的事情说三遍,demo地址

    相关文章

      网友评论

      • PGOne爱吃饺子:大佬啊 我打断点你的自定义通知的方法都不走啊
      • PGOne爱吃饺子:大佬 本地推送如何实现自定义推送界面啊
      • PGOne爱吃饺子:楼主,你的demo是不是有问题啊,跑起来看不到自定义的效果啊
      • 贺乾龙:楼主你好我工程创建了UNNotificationContentExtension现在打包如何安装在iOS10以下的设备呢
        希达like:喔喔 这个我没有自己印证 不过我同事用的是serviceExtension 就没有不可安装到iOS10以下的问题 难道contentExtension 和serviceExtension 还不一样
        贺乾龙:@希达like 如果打包了,iOS10以后的设备就不能安装了,不知道这个地方可以判断不
        希达like:不会影响iOS10以下的设备啊 iOS10以下的就不会走到extension里面了
      • 你健哥:多target的项目 需要在每个target分别创建scene跟service么? 如果我有4个target那一共就需要创建5个文件夹么?
      • 洁简:UNNotificationAction设置后没显示什么原因
      • 农夫三全:您好,为什么我这远程推送的时候始终不走service里面的方法呢?在线急等:pensive:
      • 农夫三全:您好,我这远程推送的时候始终进不去service里面方法是怎么回事呢?
        执天:貌似和 ipone机型 和 ios版本 有关,
        我这边是可以进方法,但不会被断点断住
      • e0e2e85955d9: 我运行demo好像 UNNotificationContentExtension没有走哦,只走了UNNotificationServiceExtension,不清楚怎么回事
        不想敲代码:请问解决没 ? 我也遇到这个问题了
      • 小包包包:楼主,我想问下,如果是 本地推送,不用使用扩展,如果需要远程推送展示图片,有两种,一种UNNotificationServiceExtension,另外一种UNNotificationContentExtension,如果只是简单的右侧展示小图片,用UNNotificationServiceExtension就行,如果需要自定义,那么就需要用 UNNotificationContentExtension,不知我的理解是否正确?这俩还有其他的区别吗?
        年轻就要活出样:@lcsimon 我本地创建的 UNNotificationContentExtension 好像也不走,你解决了吗?
        e0e2e85955d9:我运行demo好像 UNNotificationContentExtension没有走哦,只走了UNNotificationServiceExtension
        asaBoat:UNNotificationServiceExtension就像名字一样是用来提供通知数据服务的,UNNotificationContentExtension作用是根据通知数据自定义通知界面的。
      • 00bb77ad31da:请问怎么将 右上角的 关闭去掉?
      • e971db44fc15:非常详细!谢谢大神的无私奉献!
      • 47God:您好, 问一下, 如何设置在下拉通知栏里只显示,只显示最新的推送呢,之前的通知信息被替换掉
      • Jackey_song:你分享的Demo有问题,AFNWorking的解决方案,你说的详细一些吧
      • 低调绅士:博主 能给联系方式吗 有点问题探讨下~~
      • Xfcmy:@Bc_wh1te_Le1 我在demo里面生成了一张图片,存放在app对应的目录中,然后将filePath推送给NotificationContentExtension,然后在拓展中取出图片并显示。但是用模拟器的时候图片可以显示出来,用真机测试的时候却取到了空值请问是为什么
        Xfcmy:@Bc_wh1te_Le1 是不是要通过App Groups来共享数据
        Bc_wh1te_Le1:@Xfcmy 而且一般 写文件最好写cache里 写document里 需要特殊标记 否则审核不过。
        Bc_wh1te_Le1:@Xfcmy 真机和模拟器沙盒环境不是完全一致的。
      • Bc_wh1te_Le1:楼主 UNNotificationExtensionCategory这个可以设置多个值 那么是如何对应不同的UI呢? 这里不是只有一个VC么?
      • butterflyer:博主,怎么跑你下面的程序啊。没法断点调试。。。怎么才能跑
      • 花开半夏已成殇:请问下生成这个类以后总是报错你怎么处理的呢?
      • 颠倒的结尾: [self.extensionContext mediaPlayingStarted]; 请问博主这个播放的是什么啊
      • Bc_wh1te_Le1:- (void)didReceiveNotification:(UNNotification *)notification {
        NSDictionary *dict = notification.request.content.userInfo;
        self.label.text = notification.request.content.body;
        [self.imageView setImage:[UIImage imageNamed:@"icon-29"]];
        }
        我这样设置 发现这个extension的图片不显示
        Bc_wh1te_Le1:@Bc_wh1te_Le1 自己答复 这个extension和app的资源沙盒路径不同 不能直接访问app的资源
      • Bc_wh1te_Le1:赞了 等了好久终于更新这部分啦 :+1: :+1: :+1: :+1: :+1: :+1:
      • XCodeing:Mark了,回头看看
      • 随心吧:不错不错,要是能分享demo就更好了
        随心吧:@徐不同 好滴:sweat::blush:
        徐不同:@iOS开发学习与分享zwj demo在最下面:v:🏻

      本文标题:iOS10推送必看UNNotificationContentEx

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