zoukankan      html  css  js  c++  java
  • iOS10 推送必看 UNNotificationContentExtension

    来源:徐不同(@2016徐小爷) 

    链接:http://www.jianshu.com/p/45933f5450a4

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

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

    1、UNNotificationContentExtension

    1.1、UNNotificationContentExtension简介

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

     

    上面的两张图就是我们将要做出的效果,在自定义View的区域,你可以放上个视频,放上个日历,放上个显示地理位置的Label,总而言之,我们可以自定义View!

    1.2、如何新建一个UNNotificationContentExtension

    创建这个UNNotificationContentExtension的Target,类似于创建UNNotificationServiceExtension的步骤。

    第一步:创建

     

    第二步:选择创建类型

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

     

    1.3、如何使用以及相关Demo

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

     

    >0.Info.plist

    在这个NSExtensionAttributes的字典下面,我们有三个属性可以添加

    一.UNNotificationExtensionCategory.

    (必须要有,系统已经创建好)

    解释:对应这个key的值,可以是一个字符串,也可以是一个数组,每一个字符串都是一个identifier,这个identifier对应着每一个UNMutableNotificationContent的categoryIdentifier的属性。

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

     

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

    // 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已经可以显示出来了。如下图(请忽略下面的策略等按钮):

     

    具体位置,大家可以通过重写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地址

    https://github.com/CoderWQ/XZPushTest/tree/master

  • 相关阅读:
    HDU 4611 Balls Rearrangement 数学
    Educational Codeforces Round 11 D. Number of Parallelograms 暴力
    Knockout.Js官网学习(简介)
    Entity Framework 关系约束配置
    Entity Framework Fluent API
    Entity Framework DataAnnotations
    Entity Framework 系统约定配置
    Entity Framework 自动生成CodeFirst代码
    Entity Framework CodeFirst数据迁移
    Entity Framework CodeFirst尝试
  • 原文地址:https://www.cnblogs.com/fengmin/p/5991724.html
Copyright © 2011-2022 走看看