iOS10 通知extension之 Content Extension你玩過(guò)了嗎礁遣?

在看之前如果你對(duì)iOS10 的推送還處于一片空白屋摔,建議先看<a href="http://www.reibang.com/p/1f3501dd232a">iOS 10 推送你玩過(guò)了嗎薛匪?</a>


Notification Extension
iOS10 添加了很多的Extension,與通知相關(guān)的 extension 有兩個(gè):Service ExtensionContent Extension四敞。
我們先來(lái)了解一下Content Extension移剪,這個(gè)東西主要是干啥的呢号杏?

可以通過(guò)提前配置的categoryIdentifier來(lái)定制推送顯示的界面誓斥。
簡(jiǎn)單來(lái)說(shuō)只洒,在Content ExtensionInfo.plist中提前配置categoryIdentifier類型,當(dāng)收到的推送中的categoryIdentifierContent Extension中提前配置的categoryIdentifier一樣就會(huì)去走自定義的UI展示岖食。

看一下效果圖:


Paste_Image.png

把玩一下:
1红碑、創(chuàng)建


Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png

創(chuàng)建完畢相對(duì)于之前項(xiàng)目有啥變化:

Paste_Image.png
Paste_Image.png
Paste_Image.png

2、把玩一下
測(cè)試發(fā)送一個(gè)本地推送

// 測(cè)試按鈕的點(diǎn)擊事件5
    func clickBtn5(sender:UIButton) {
        if #available(iOS 10.0, *) {
            // 1泡垃、創(chuàng)建推送的內(nèi)容
            let content = UNMutableNotificationContent()
            content.title = "iOS 10 的推送標(biāo)題"
            content.body = "附件"
            content.subtitle = "附件"
            content.userInfo = ["name":"張三","age":"20"]
            content.categoryIdentifier = "myNotificationCategory"
            // 2析珊、創(chuàng)建發(fā)送觸發(fā)
            let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
            // 3. 發(fā)送請(qǐng)求標(biāo)識(shí)符
            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、創(chuàng)建一個(gè)發(fā)送請(qǐng)求
            let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
            
            // 5蔑穴、將請(qǐng)求添加到發(fā)送中心
            UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
                if error == nil{
                    print("Time Interval Notification scheduled: \(requestIdentifier)")
                }
            })
            
        } else {
            // Fallback on earlier versions
        }
        
    }

這個(gè)代碼和之前講解的<a href="">本地推送</a>的代碼一樣忠寻,唯一不一樣的就是<code>content.categoryIdentifier = "myNotificationCategory"</code>,
為什么要設(shè)置<code>content.categoryIdentifier = "myNotificationCategory"</code>?
因?yàn)椋?/p>

Paste_Image.png

收到推送之后

Paste_Image.png

當(dāng)下拉通知存和,查看通知詳情的時(shí)候就會(huì)走相應(yīng)的斷點(diǎn)

Paste_Image.png

什么奕剃?你的斷點(diǎn)沒(méi)走?
<1>捐腿、首先檢查你的推送的content.categoryIdentifier = "myNotificationCategory"
<2>纵朋、確定當(dāng)前調(diào)試的tag是Content Extension

Paste_Image.png

<3>、運(yùn)行的時(shí)候確定選擇的app是當(dāng)前正在運(yùn)行的app
Paste_Image.png

放過(guò)斷點(diǎn)茄袖,查看展示的UI操软。

Paste_Image.png
Paste_Image.png

3、定制有顏色的這一部分的UI


Paste_Image.png

還有個(gè)地方說(shuō)一下
Info.plist中的UNNotificationExtensionCategory不僅僅可以定制一個(gè)宪祥,可以定制多個(gè)

Paste_Image.png

變?yōu)?/p>

Paste_Image.png

代碼實(shí)現(xiàn)有顏色部分的布局:

    @available(iOSApplicationExtension 10.0, *)
    func didReceive(_ notification: UNNotification) {
        // 1聂薪、獲取需要顯示的內(nèi)容
        let content = notification.request.content
        let titleStr = content.title
        let subTitleStr = content.subtitle
        // 附件的本地url
        let finalUrl:URL? = content.attachments[0].url
        
        // 2、通過(guò) category 標(biāo)識(shí)來(lái)判斷應(yīng)該采取哪一種布局
        let category = notification.request.content.categoryIdentifier
        if category == "myNotificationCategory1" {
            // 布局蝗羊,圖片在左邊藏澳,標(biāo)題和子標(biāo)題在右邊
            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、加載存儲(chǔ)在沙盒中的附件
        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()
    }

本地推送的實(shí)現(xiàn)效果


Paste_Image.png

大體的流程實(shí)現(xiàn)是這樣的:
<1>耀找、如果推送消息中的categoryIdentifierContent ExtensionInfo.plist中提前配置UNNotificationExtensionCategory中能找到翔悠,那么會(huì)自動(dòng)走Content Extension的類。
<2>、通過(guò)不同的categoryIdentifier進(jìn)行不同的布局凉驻,獲取自己想要展示的通知中的元素
<3>腻要、如果存在多媒體的話,就直接去獲取本地路徑<PS:如果是遠(yuǎn)程推送的話涝登,會(huì)先走Service Extension,即使有通知附件雄家,也會(huì)在這個(gè)時(shí)候下載下來(lái)保存在本地了,所以直接去獲取通知的附件url就可以了>
如果Service Extension還不是很清楚的話可以參考
iOS10 通知extension之 Service Extension你玩過(guò)了嗎胀滚?

4趟济、遠(yuǎn)程推送測(cè)試一下
PS:介紹一個(gè)好用的測(cè)試工具 <a >Kunff</a>
也可以看一下<a href="http://www.reibang.com/p/5d83250fb5a1">iOS10 遠(yuǎn)程推送你玩過(guò)了嗎?</a>更好的了解下iOS10遠(yuǎn)程推送咽笼。

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
  }
}

實(shí)現(xiàn)效果:

Paste_Image.png

4顷编、這里說(shuō)一下坑點(diǎn)
<1>、剛開始的時(shí)候我是這么獲取下載圖片路徑的剑刑,因?yàn)檫h(yuǎn)程推送在Service Extension的時(shí)候就將推送的附件下載到本地媳纬,并且保存在沙盒中了,名稱我也知道施掏,這個(gè)時(shí)候我去Content Extension去直接獲取這個(gè)沙盒地址钮惠,去找這個(gè)文件的時(shí)候,發(fā)現(xiàn)找不到七芭。原因是這樣的素挽,因?yàn)槊總€(gè)target中的沙盒地址不一樣。
Paste_Image.png

Paste_Image.png

所以這種方法是不可行的狸驳。

<2>预明、直接獲取通知的附件的url去加載


Paste_Image.png

然后去直接去用這個(gè)路徑去獲取的話還是獲取不到的。

<3>耙箍、當(dāng)需要訪問(wèn)不在 App 自身的沙盒或者自身共享容器里的資源時(shí)撰糠,需要申請(qǐng)權(quán)限訪問(wèn),使用到 NSURL 的兩個(gè)方法:
開始安全訪問(wèn):- (BOOL)startAccessingSecurityScopedResource
停止安全訪問(wèn):- (void)stopAccessingSecurityScopedResource

也就是需要這么訪問(wèn)
// 附件的本地的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()
}
但是這么訪問(wèn)另一個(gè)奇葩的問(wèn)題出來(lái)了辩昆。
本地推送的效果:


yuan'ch

遠(yuǎn)程推送的效果:


Paste_Image.png

報(bào)錯(cuò)信息:

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

具體的原因沒(méi)找到窗慎,找到一個(gè)類似的原因,說(shuō)在讀取文件的時(shí)候卤材,文件被刪除了,所以為了阻止這種情況的出現(xiàn)峦失,要先把文件轉(zhuǎn)化成data對(duì)象扇丛,然后在讀取的時(shí)候再轉(zhuǎn)成圖片。

所以最終的版本:

// 附件的本地的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()
        }

最終實(shí)現(xiàn)愉快的顯示

本地推送尉辑,自動(dòng)布局


Paste_Image.png

遠(yuǎn)程推送自動(dòng)布局

Paste_Image.png

5帆精、擴(kuò)展
<1>、介紹下這個(gè)UNNotificationExtensionDefaultContentHidden配置參數(shù)

Paste_Image.png

這個(gè)參數(shù)什么作用?
直接看圖比較直接卓练,兩圖頂多言隘蝎。
UNNotificationExtensionDefaultContentHidden = YES的時(shí)候


Paste_Image.png

UNNotificationExtensionDefaultContentHidden = NO的時(shí)候


Paste_Image.png

<2>、介紹下這個(gè)UNNotificationExtensionInitialContentSizeRatio配置參數(shù)

Paste_Image.png

這個(gè)參數(shù)什么作用襟企?
這個(gè)值是一定要有的嘱么,系統(tǒng)已經(jīng)默認(rèn)創(chuàng)建好了
這個(gè)值的類型是一個(gè)浮點(diǎn)類型,代表的是高度與寬度的比值顽悼。系統(tǒng)會(huì)使用這個(gè)比值曼振,作為初始化view的大小。舉個(gè)簡(jiǎn)單的例子來(lái)說(shuō)蔚龙,如果該值為1冰评,則該視圖為正方
形。如果為0.5木羹,則代表高度是寬度的一半甲雅。
注意這個(gè)值只是初始化的一個(gè)值,在這個(gè)擴(kuò)展添加后坑填,可以重寫frame抛人,展示的時(shí)候,在我們還沒(méi)打開這個(gè)視圖預(yù)覽時(shí)穷遂,背景是個(gè)類似圖片占位的灰色函匕,那個(gè)灰色的高度寬度
之比,就是通過(guò)這個(gè)值來(lái)設(shè)定蚪黑。
直接上圖

Paste_Image.png

Paste_Image.png

當(dāng)UNNotificationExtensionInitialContentSizeRatio = 1的時(shí)候
Paste_Image.png

<3>盅惜、現(xiàn)在的界面要不就太高,要不就太低忌穿,怎么搞抒寂?來(lái)看一下preferredContentSize這個(gè)屬性。

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

這樣就能動(dòng)態(tài)的計(jì)算想要顯示的內(nèi)容的整體的大小了掠剑,但是不好的地方就是屈芜,等內(nèi)容加載出來(lái)之后會(huì)有個(gè)變大或者變小的動(dòng)畫。不過(guò)還能接受朴译。


Paste_Image.png
Paste_Image.png

關(guān)于斷點(diǎn)調(diào)試井佑,參考下面的文章,下面的位置有相關(guān)的說(shuō)明:
http://www.reibang.com/p/5fc3b4155257

最后眠寿,獻(xiàn)上參考Demo地址:https://github.com/RunOfTheSnail/PushDemo001

參考資料:
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
圖畫的不錯(cuò)
http://www.reibang.com/p/2f3202b5e758
http://www.cocoachina.com/ios/20161021/17820.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末躬翁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盯拱,更是在濱河造成了極大的恐慌盒发,老刑警劉巖例嘱,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宁舰,居然都是意外死亡拼卵,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門蛮艰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腋腮,“玉大人,你說(shuō)我怎么就攤上這事印荔〉秃” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵仍律,是天一觀的道長(zhǎng)嘿悬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)水泉,這世上最難降的妖魔是什么善涨? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮草则,結(jié)果婚禮上钢拧,老公的妹妹穿的比我還像新娘。我一直安慰自己炕横,他們只是感情好源内,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著份殿,像睡著了一般膜钓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上卿嘲,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天颂斜,我揣著相機(jī)與錄音,去河邊找鬼拾枣。 笑死沃疮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梅肤。 我是一名探鬼主播司蔬,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姨蝴!你這毒婦竟也來(lái)了俊啼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤似扔,失蹤者是張志新(化名)和其女友劉穎吨些,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炒辉,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豪墅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了黔寇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偶器。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖缝裤,靈堂內(nèi)的尸體忽然破棺而出屏轰,到底是詐尸還是另有隱情,我是刑警寧澤憋飞,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布霎苗,位于F島的核電站,受9級(jí)特大地震影響榛做,放射性物質(zhì)發(fā)生泄漏唁盏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一检眯、第九天 我趴在偏房一處隱蔽的房頂上張望厘擂。 院中可真熱鬧,春花似錦锰瘸、人聲如沸刽严。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)舞萄。三九已至,卻和暖如春恕曲,著一層夾襖步出監(jiān)牢的瞬間鹏氧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工佩谣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留把还,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓茸俭,卻偏偏與公主長(zhǎng)得像吊履,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子调鬓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容