Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is There A Better Way To Use An Image From Assets.xcassets In A Notification Attachment Than This?

Tags:

ios

swift

I want to attach an image from Assets.xcassets to a notification. I have been looking for a solution for about an hour now and it seems like the only way to do this:

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")

guard fileManager.fileExists(atPath: url.path) else {
    guard
        let image = UIImage(named: name),
        let data = UIImagePNGRepresentation(image)
        else { return nil }

    fileManager.createFile(atPath: url.path, contents: data, attributes: nil)
    return url
}

return url
}

Source : Can I get a NSURL from an XCAssets bundle?

Which seems like overkill. However as far as I can tell that's the only way to get an URL you can use:

let imageURL = createLocalUrl(forImageNamed: "TestImage")

let attachment = try! UNNotificationAttachment(identifier: "image", url: imageURL!, options: [:])
        content.attachments = [attachment]

Is there a better way to add images from Assets.xcassets to local notifications? (Yes I know I can store images outside Assets and use Bundle.main.etc)

like image 818
Ian Kohlert Avatar asked Oct 17 '22 15:10

Ian Kohlert


2 Answers

I know this is old question, but I improve Your solution a little bit, and maybe someone use it

extension UIImage {
    func createLocalURL() -> URL? {
        guard let imageName = self.accessibilityIdentifier else {
            return nil
        }

        let fileManager = FileManager.default
        guard let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {
            return nil
        }
        let url = cacheDirectory.appendingPathComponent("\(imageName).png")

        guard fileManager.fileExists(atPath: url.path) else {
            guard let data = self.pngData() else { return nil }
            fileManager.createFile(atPath: url.path, contents: data, attributes: nil)
            return url
        }

        return url
    }
}

In class when You want to use it

func createImageAttachment(image: UIImage?) -> [UNNotificationAttachment] {
        var notificationAttachment: [UNNotificationAttachment] = []
        if let image = image,
            let imageUrl = image.createLocalURL(),
            let attachment = try? UNNotificationAttachment(identifier: "image", url: imageUrl, options: nil) {

            notificationAttachment.append(attachment)
        }

        return notificationAttachment
    }

And add image to notification

let image = UIImage(named: "TestImage")
content = createImageAttachment(image: image)

It's safer way

like image 64
JamesVoo Avatar answered Nov 15 '22 07:11

JamesVoo


It is also possible to do this:

extension UIImage {
    func getURL() -> URL? {
         guard let base64Image = pngData()?.base64EncodedString() else { return nil }
         return URL(string: "data:image/png;base64,\(base64Image)")
    }
}

And called it:

 let imageURL = UIImage(named: "TestImage")?.getURL()

 let attachment = try! UNNotificationAttachment(identifier: "image", url: imageURL!, options: [:])
    content.attachments = [attachment]
like image 33
Alberto Cantallops Avatar answered Nov 15 '22 06:11

Alberto Cantallops