这里每天分享一个 iOS 的新知识,快来关注我吧
在之前的文章中,已经介绍过一些关于推送的内容:
大概从 iOS 15 开始注意到一些日常使用的 App 的推送可以自定义 logo 了,比如系统电话、FaceTime、iMessage、微博、淘宝等等。
研究了一下方法,这里分享给大家。
这次教程的前提是你的 App 已经支持推送了,如果还不支持推送,需要先配置普通的推送。
添加 NotificationService
如果你的应用中还没有添加 NotificationService,需要先添加这个 Target,这是 iOS 10 开始新增的通知服务,可以在不打开 App 的情况下执行一些推送触发的代码。
点击顶部导航 File -> New -> Target...
或者是在 Target 下点击加号,也是一样的
然后在弹出的面板上选择 Notification Service Extension 选项,随后点击下一步,输入名字点击确定即可:
添加这个 Target 之后,Xcode 会为我们生成一个新的文件夹,里边有一个 NotificationService 的 swift 文件,这个文件一会儿会用到。
Communication Notifications (通讯通知)
除了 Notification Service 之外还需要使用 Communication Notifications(通讯通知),今天教给大家修改推送头像的功能主要就是由这个扩展实现的。
首先选择项目根目录,选中你的 Target,然后在 Signing & Capabilities 部分,点击 + Capability
在弹出的页面上输入 Notification,双击 Communication Notifications 添加进来。
设置 info.plist
在实现通信通知之前,还需要在你的 info.plist 文件中新增一个 NSUserActivityTypes 的数组,里边添加一个 INSendMessageIntent
代码部分
最后就是最重要的代码部分了,打开 NotificationService.swift 文件,可以看到有这样一个方法:
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
}
这个方法会在手机接收到推送的时候调用,因为这个 Extension 是运行在一个独立进程里的,所以即使你的 App 没有启动,这里的代码也会正常执行,很多 App 利用这个特性上报一个推送到达的埋点,以便于统计真实的推送送达率。
扯远了,我们需要在这个方法里实现配置自定义图片的代码:
// 将图片下载下来
private func download(url: URL, handler: @escaping (_ data: Data?) -> Void) {
let task = URLSession.shared.dataTask(with: url, completionHandler: {
data, _, _ in
handler(data)
})
task.resume()
}
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if #available(iOSApplicationExtension 15.0, *),
let userInfo = bestAttemptContent?.userInfo,
let appIconUrl = userInfo["custom_icon_url"] as? String,
let url = URL(string: appIconUrl) {
let title = bestAttemptContent?.title
let subTitle = bestAttemptContent?.subtitle
let body = bestAttemptContent?.body
download(url: url) { data in
guard let data = data else {
return
}
// Initialize only the sender for a one-to-one message intent.
let handle = INPersonHandle(value: "", type: .unknown)
let avatar = INImage(imageData: data)
let sender = INPerson(personHandle: handle,
nameComponents: PersonNameComponents(),
displayName: title,
image: avatar,
contactIdentifier: nil,
customIdentifier: nil)
// Because this communication is incoming, you can infer that the current user is
// a recipient. Don't include the current user when initializing the intent.
let intent = INSendMessageIntent(recipients: nil,
outgoingMessageType: .outgoingMessageText,
content: body,
speakableGroupName: nil,
conversationIdentifier: nil,
serviceName: nil,
sender: sender,
attachments: nil)
// Use the intent to initialize the interaction.
let interaction = INInteraction(intent: intent, response: nil)
// Interaction direction is incoming because the user is
// receiving this message.
interaction.direction = .incoming
// Donate the interaction before updating notification content.
interaction.donate { error in
if error != nil {
// Handle errors that may occur during donation.
return
}
// After donation, update the notification content.
let content = request.content
do {
// Update notification content before displaying the
// communication notification.
let updatedContent = try content.updating(from: intent)
// Call the content handler with the updated content
// to display the communication notification.
contentHandler(updatedContent)
} catch {
// Handle errors that may occur while updating content.
}
}
}
return
}
if let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
代码比较多,稍微解释一下。
didReceive(:, withContentHandler:) 方法会在用户收到推送的时候调用,我们需要在这个方法内做出对推送内容的更改。
首先拿到 push 下发的图片用 download 方法下载下来,生成 INImage 图片对象,然后创建一个 INPerson 对象,之后再创建 INInteraction 实例,最后使用 donate 方法来让本次改动生效。
要推送一条消息,都需要一个 Payload 文件,它是 JSON 格式的,这在以前的文章中也介绍过,我们这里自定义了一个 key:custom_icon_url,它位于最 JSON 的外层:
{
"aps" : {
"alert" : {
"title" : "模拟器推送,标题",
"subtitle" : "副标题",
"body" : "这里是推送内容"
},
"mutable-content": 1,
"badge" : 1
},
"custom_icon_url": "你的自定义图片链接"
}
按照以上步骤操作,最后就能实现更换推送 Icon 的功能了。
点击下方公众号卡片,关注我,每天分享一个关于 iOS 的新知识
本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!