iOS / FCM - How to use Image name from Payload to display an Image from XCAsset folder as Notification Attachment?

不想你离开。 提交于 2019-12-08 17:13:54

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!