Notification iOS10

Notification Extension

iOS10 添加了很多的 Extension ,与通知相关的 extension 有两个: Service ExtensionContent Extension


我们先来了解一下 Content Extension ,这个东西主要是干啥的呢?


可以通过提前配置的 categoryIdentifier 来定制推送显示的界面。


简单来说,在 Content ExtensionInfo.plist 中提前配置 categoryIdentifier 类型,当收到的推送中的 categoryIdentifierContent Extension 中提前配置的 categoryIdentifier 一样就会去走自定义的UI展示。


看一下效果图:



Paste_Image.png


把玩一下:


1、创建



Paste_Image.png



Paste_Image.png



Paste_Image.png



Paste_Image.png


创建完毕相对于之前项目有啥变化:



Paste_Image.png



Paste_Image.png



Paste_Image.png


2、把玩一下


测试发送一个本地推送


// 测试按钮的点击事件5 
func clickBtn5(sender:UIButton) {
if #available(iOS 10.0, *) {
// 1、创建推送的内容
let content = UNMutableNotificationContent()
content.title = "iOS 10 的推送标题"
content.body = "附件"
content.subtitle = "附件"
content.userInfo = ["name":"张三","age":"20"]
content.categoryIdentifier = "myNotificationCategory"
// 2、创建发送触发
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
// 3. 发送请求标识符
let requestIdentifier = "music"
// 添加图片
if let imageURL = Bundle.main.url(forResource: "二哈", withExtension: "jpg"),
let attachment = try? UNNotificationAttachment(identifier: "imageAttachment", url: imageURL, options: nil)
{
content.attachments = [attachment]
}
        //             添加视频
        //            if let videoURL = Bundle.main.url(forResource: "IMG_2077", withExtension: "MOV"),
        //                let attachment = try? UNNotificationAttachment(identifier: "videoAttachment", url: videoURL, options: nil)
        //            {
        //                content.attachments = [attachment]
        //            }

        //            // 添加音频
        //            if let videoURL = Bundle.main.url(forResource: "聂芦苇+-+东京热", withExtension: "mp3"),
        //                let attachment = try? UNNotificationAttachment(identifier: "voiceAttachment", url: videoURL, options: nil)
        //            {
        //                content.attachments = [attachment]
        //            }

        // 4、创建一个发送请求
        let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)

        // 5、将请求添加到发送中心
        UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
            if error == nil{
                print("Time Interval Notification scheduled: \(requestIdentifier)")
            }
        })

    } else {
        // Fallback on earlier versions
    }

}</code></pre> 

这个代码和之前讲解的 本地推送 的代码一样,唯一不一样的就是 content.categoryIdentifier = “myNotificationCategory” ,


为什么要设置 content.categoryIdentifier = “myNotificationCategory” ?


因为:



Paste_Image.png


收到推送之后



Paste_Image.png


当下拉通知,查看通知详情的时候就会走相应的断点



Paste_Image.png


什么?你的断点没走?


<1>、首先检查你的推送的 content.categoryIdentifier = “myNotificationCategory”


<2>、确定当前调试的tag是 Content Extension



Paste_Image.png


<3>、运行的时候确定选择的app是当前正在运行的app



Paste_Image.png


放过断点,查看展示的UI。



Paste_Image.png



Paste_Image.png


3、定制有颜色的这一部分的UI



Paste_Image.png


还有个地方说一下


Info.plist中的 UNNotificationExtensionCategory 不仅仅可以定制一个,可以定制多个



Paste_Image.png


变为



Paste_Image.png


代码实现有颜色部分的布局:


@available(iOSApplicationExtension 10.0, *) 
func didReceive(_ notification: UNNotification) {
// 1、获取需要显示的内容
let content = notification.request.content
let titleStr = content.title
let subTitleStr = content.subtitle
// 附件的本地url
let finalUrl:URL? = content.attachments[0].url
    // 2、通过 category 标识来判断应该采取哪一种布局
    let category = notification.request.content.categoryIdentifier
    if category == "myNotificationCategory1" {
        // 布局,图片在左边,标题和子标题在右边
        contentImageView.frame = CGRect(x: 10, y: 10, width:self.view.frame.width*(1/3.0), height: self.view.frame.width*(1/3.0))
        contentImageView.backgroundColor = UIColor.cyan
        contentImageView.contentMode = UIViewContentMode.scaleAspectFit
        let  titleLabelX = self.contentImageView.frame.maxX+10
        self.titleLabel.frame = CGRect(x: titleLabelX, y: 10, width: self.view.frame.width-titleLabelX-10, height: 0)

    }

    // 3、加载存储在沙盒中的附件
    if (finalUrl?.startAccessingSecurityScopedResource())!{
        print("finalUrl = \(finalUrl)     finalUrl.path = \(finalUrl?.path)")

        let tempImage = UIImage(contentsOfFile: finalUrl!.path)
        let imageDate = UIImageJPEGRepresentation(tempImage!, 1.0)
        let operateImage = UIImage.init(data: imageDate!)

        contentImageView.image = operateImage
        subImageView.image = operateImage //UIImage(contentsOfFile: finalUrl!.path)
        subImageView.contentMode = UIViewContentMode.scaleAspectFit
        finalUrl?.stopAccessingSecurityScopedResource()
    }

    // 更新titleLabel的值
    self.titleLabel.text = titleStr
    self.titleLabel.sizeToFit()

    // 重新布局 subTitleLabel
    self.subTitleLabel.frame = CGRect(x: self.titleLabel.frame.minX, y: self.titleLabel.frame.maxY+5, width:self.view.frame.width*(1/3.0), height: 0)
    self.subTitleLabel.text = subTitleStr
    self.subTitleLabel.sizeToFit()
}</code></pre> 

本地推送的实现效果



Paste_Image.png


大体的流程实现是这样的:


<1>、如果推送消息中的 categoryIdentifierContent ExtensionInfo.plist 中提前配置 UNNotificationExtensionCategory 中能找到,那么会自动走 Content Extension 的类。


<2>、通过不同的 categoryIdentifier 进行不同的布局,获取自己想要展示的通知中的元素


<3>、如果存在多媒体的话,就直接去获取本地路径<PS:如果是远程推送的话,会先走Service Extension,即使有通知附件,也会在这个时候下载下来保存在本地了,所以直接去获取通知的附件url就可以了>


4、远程推送测试一下



Paste_Image.png


{ 
"aps":{
"alert":{
"title":"iOS 10 title",
"subtitle":"iOS 10 subtitle",
"body":"iOS 10 body"
},
"my-attachment":"http://img01.taopic.com/160317/240440-16031FU23937.jpg",
"mutable-content":1,
"category":"myNotificationCategory1",
"sound":"default",
"badge":3
}
}

实现效果:



Paste_Image.png


5、这里说一下坑点


<1>、刚开始的时候我是这么获取下载图片路径的,因为远程推送在 Service Extension 的时候就将推送的附件下载到本地,并且保存在沙盒中了,名称我也知道,这个时候我去 Content Extension 去直接获取这个沙盒地址,去找这个文件的时候,发现找不到。原因是这样的,因为每个target中的沙盒地址不一样。



Paste_Image.png



Paste_Image.png


所以这种方法是不可行的。


<2>、直接获取通知的附件的url去加载



Paste_Image.png


然后去直接去用这个路径去获取的话还是获取不到的。


<3>、当需要访问不在 App 自身的沙盒或者自身共享容器里的资源时,需要申请权限访问,使用到 NSURL 的两个方法:


开始安全访问: - (BOOL)startAccessingSecurityScopedResource


停止安全访问: - (void)stopAccessingSecurityScopedResource


也就是需要这么访问


// 附件的本地的url


let finalUrl:URL? = content.attachments[0].url


if (finalUrl?.startAccessingSecurityScopedResource())!{


contentImageView.image = UIImage(contentsOfFile: finalUrl!.path)


subImageView.image = UIImage(contentsOfFile: finalUrl!.path)


subImageView.contentMode = UIViewContentMode.scaleAspectFit


finalUrl?.stopAccessingSecurityScopedResource()


}


但是这么访问另一个奇葩的问题出来了。


本地推送的效果:



yuan’ch


远程推送的效果:



Paste_Image.png


报错信息:


ImageIO: createDataWithMappedFile:1322:  'open' failed '/var/mobile/Library/SpringBoard/PushStore/Attachments/com.yanzhang.PushDemo001/c9e9b97a225eeddad295d3a7840101df60d91099.jpeg' 
error = 1 (Operation not permitted)

具体的原因没找到,找到一个类似的原因,说在读取文件的时候,文件被删除了,所以为了阻止这种情况的出现,要先把文件转化成data对象,然后在读取的时候再转成图片。


所以最终的版本:


// 附件的本地的url 
let finalUrl:URL? = content.attachments[0].url
if (finalUrl?.startAccessingSecurityScopedResource())!{
        let tempImage = UIImage(contentsOfFile: finalUrl!.path)
        let imageDate = UIImageJPEGRepresentation(tempImage!, 1.0)
        let operateImage = UIImage.init(data: imageDate!)

        contentImageView.image = operateImage
        subImageView.image = operateImage //UIImage(contentsOfFile: finalUrl!.path)
        subImageView.contentMode = UIViewContentMode.scaleAspectFit
        finalUrl?.stopAccessingSecurityScopedResource()
    }</code></pre> 

最终实现愉快的显示


本地推送,自动布局



Paste_Image.png


远程推送自动布局



Paste_Image.png


6、扩展


<1>、介绍下这个 UNNotificationExtensionDefaultContentHidden 配置参数



Paste_Image.png


这个参数什么作用?


直接看图比较直接,两图顶多言。


UNNotificationExtensionDefaultContentHidden = YES的时候



Paste_Image.png


UNNotificationExtensionDefaultContentHidden = NO的时候



Paste_Image.png


<2>、介绍下这个 UNNotificationExtensionInitialContentSizeRatio 配置参数



Paste_Image.png


这个参数什么作用?


这个值是一定要有的,系统已经默认创建好了


这个值的类型是一个浮点类型,代表的是高度与宽度的比值。系统会使用这个比值,作为初始化view的大小。举个简单的例子来说,如果该值为1,则该视图为正方


形。如果为0.5,则代表高度是宽度的一半。


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


之比,就是通过这个值来设定。


直接上图



Paste_Image.png



Paste_Image.png


UNNotificationExtensionInitialContentSizeRatio = 1 的时候



Paste_Image.png


<3>、现在的界面要不就太高,要不就太低,怎么搞?来看一下 preferredContentSize 这个属性。


// 修改整体的高度 
preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: 150)

这样就能动态的计算想要显示的内容的整体的大小了,但是不好的地方就是,等内容加载出来之后会有个变大或者变小的动画。不过还能接受。



Paste_Image.png



Paste_Image.png


 


参考资料:


http://www.cocoachina.com/ios/20160628/16833.html


https://onevcat.com/2016/08/notification/


http://www.cnblogs.com/lidongq/p/5968923.html


https://developer.apple.com/reference/usernotifications/unnotificationattachment


 


来自:http://www.jianshu.com/p/00f671d204d4


 

            </article>

转自:http://xfenglin.com/a/12010804010.html?ref=myread

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值