问题
I am working on Rich Notification for a Weather App which is sent via FCM.
First of all, I would like to inform you that my notifications are sent and received successfully both with APNS and FCM.
I am using Pusher and Postman in order to test everything.
CONTEXT
Here is the Payload I am sending through Postman
{
"to": "/topics/03772",
"content_available": true,
"mutable_content": true,
"priority": "high",
"notification": {
"title": "Daily forecast",
"body": "Blue sky, no clouds",
"sound": "default",
"click_action": "weather"
},
"data": {
"timestamp": "1506103200",
"code": "03772",
"city": "London",
"attch": "7a",
"t": "15˚",
}
}
I like this Payload
format, I know it's working, it feels clear to me and easy to understand.
EXPLANATIONS:
Users can subscribe to a topic by adding a city as a Favorite city. The topic is the city code.
The data
part is the weather data sending from the server.
Here is my didReceive
method :
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
func failEarly() {
contentHandler(request.content)
}
guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
return failEarly()
}
let attachment = try! UNNotificationAttachment(identifier: "image",
url: Bundle.main.url(forResource: "12_c", withExtension: "png")!,
options: nil)
let category = UNNotificationCategory(identifier: "weather", actions: [], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
content.attachments = [attachment]
contentHandler(content.copy() as! UNNotificationContent)
}
I am directly testing with an image name from Bundle, but it is not working.
QUESTION
How can I save to the disk the PNG Representation of an UIImage from the xcassets folder?
Indeed, the key/value "attch": "7a"
from the Payload is the the code for the weather image to display in the notification as attachment. I have saved all the images in my xcassets folder (with same code name)
I need to:
- Get the image name received in the Notification
- Get the associated image in xcassets folder
- Copy the PNG representation of the image to FileManager (disk)
- Set it as Attachment for the Notification
EDIT: RESOLVED!
My question is resolved thanks to an answer from an other question which is not even marked as accepted answer, but it helped me, for this one.
Indeed, people might want to do the same as I did, or didn't even think about what can be achieve with Notifications.
In all the examples or guides that I read, they explain how to download an image and set it as attachment for you notification.
But it can also be done with local image from xcassets folder. People can now learn how it can be applied for this specific purpose.
The number of upvotes showed me that people were in the same situation as I did, and they probably learned from this question/answer.
Here is my final didReceive method :
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttempContent = bestAttemptContent {
// Modify the notification content here
let userInfo : [AnyHashable: Any] = bestAttempContent.userInfo
if let imgName = userInfo["attch"] {
if let url = createLocalUrl(forImageNamed: imgName as! String) {
do {
let attachment = try UNNotificationAttachment(identifier: "weather", url: url, options: nil)
defer {
self.bestAttemptContent?.attachments = [attachment]
}
}
catch {
print("Could not set UNNotificationAttachment")
}
}
}
contentHandler(bestAttempContent)
}
}
And the method I found on SO :
func createLocalUrl(forImageNamed name: String) -> URL? {
let fileManager = FileManager.default
let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let url = cacheDirectory.appendingPathComponent("\(name).png")
let path = url.path
guard fileManager.fileExists(atPath: path) else {
guard
let image = UIImage(named: name),
let data = UIImagePNGRepresentation(image)
else { return nil }
fileManager.createFile(atPath: path, contents: data, attributes: nil)
return url
}
return url
}
I hope it helped you.
回答1:
If I have this correctly, you would like to use the attch
property's value as an image name to form a url from local storage (.xcassets).
The payload content is JSON, so should be able to access attch
using dot syntax:
let fileName: String = request.content.data.attch
Then form a URL to the Resource and attach it. (I'm assuming its "7a.jpg")
if let url = Bundle.main.url(forResource: fileName, withExtension: "jpg") {
//The Image exists
let attachment = try! UNNotificationAttachment(identifier: "image",
url: url, options: nil)
content.attachments = [attachment]
} else {
//Unable to get/find image, use a default one.
let attachment = try! UNNotificationAttachment(identifier: "image",
url: Bundle.main.url(forResource: "12_c", withExtension: "png")!, options: nil)
content.attachments = [attachment]
}
来源:https://stackoverflow.com/questions/49360386/ios-fcm-how-to-use-image-name-from-payload-to-display-an-image-from-xcasset