2

I have Image cache mechanism in my app. I also need to show local notifications with images. I have a problem. When I try to set UNNotificationAttachment with an image, I get an image from my cache or, if an image doesn't exist, I download it and cache. Then I build a URL to Caches directory, but when I pass this URL to UNNotificationAttachment, I get an error: NSLocalizedDescription=Invalid attachment file URL. What do I make wrong?

if let diskUrlString = UIImageView.sharedImageCache.diskUrlForImageUrl(imageUrl) {
    if let diskUrl = URL(string: diskUrlString) {
       do {
            res = try UNNotificationAttachment(identifier: imageUrlString, url: diskUrl, options: nil)
        } catch (let error) {
            print("error", error)
            // Invalid attachment file URL
        }
    }
}

func diskUrlForImageUrl(_ imageUrl: URL) -> String? {
    let urlRequest = URLRequest(url: imageUrl)
    return ImageCache.cacheDirectory.appending("/\(ImageCache.imageCacheKeyFromURLRequest(urlRequest))")
}

static fileprivate var cacheDirectory: String = { () -> String in
    let documentsDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
    let res = documentsDirectory.appending("/scAvatars")
    let isExist = FileManager.default.fileExists(atPath: res, isDirectory: nil)
    if !isExist {
        try? FileManager.default.createDirectory(atPath: res, withIntermediateDirectories: true, attributes: nil)
    }
    return res
}()
Arasuvel
  • 2,971
  • 1
  • 25
  • 40
Valentin Shamardin
  • 3,569
  • 4
  • 34
  • 51

3 Answers3

0

I have found that if I add a prefix file:///private to diskUrlString, then URL builds like expected. But I didn't still understand, how to build the url without hardcoding this prefix. So now I can use both cache and UNNotificationAttachment!

Valentin Shamardin
  • 3,569
  • 4
  • 34
  • 51
0

The problem here is that you are using a path, not a URL. A path is a string, like "/var/log/foo.log". A URL is semantically more complex than a path. You need a URL that describes the location of the image file on the device file system.

Build a properly constructed URL to the image file and the attachment may work. The attachment may also need a type identifier hint to tell iOS what kind of data is in the file.

quellish
  • 21,123
  • 4
  • 76
  • 83
-1

You do not have to use urls. You can use image data with UNNotificationAttachment.

Here is a sample code.

let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
            
let imageURL = URL(fileURLWithPath: paths.first!).appendingPathComponent("\(fileName).jpg")
let image = UIImage(contentsOfFile: imageURL.path)
let imageData = image?.pngData()

            
if let unwrappedImageData = imageData, let attachement = try? UNNotificationAttachment(data: unwrappedImageData, options: nil) {
    content.attachments = [attachement]
}
Ankahathara
  • 2,866
  • 2
  • 20
  • 26