Can I get a NSURL from an XCAssets bundle?
If you're targeting iOS 7+, Xcode 5 now puts the assets into a new file format. 1 file for all of the assets. This means you can not get access to the file directly.
If you need to access the file directly, you can include it as an normal image outside of an asset catalog.
I wanted to access some vector assets for creating UNNotificationAttachment
with local resources so I came up with this helper class. It basically just gets image from assets, saves its data to disk and return file URL. I hope that helps someone.
import UIKit
class AssetExtractor {
static 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
}
}
Swift 5
And it made a bit more sense to me as a URL extension.
extension URL {
static func localURLForXCAsset(name: String) -> URL? {
let fileManager = FileManager.default
guard let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {return nil}
let url = cacheDirectory.appendingPathComponent("\(name).png")
let path = url.path
if !fileManager.fileExists(atPath: path) {
guard let image = UIImage(named: name), let data = image.pngData() else {return nil}
fileManager.createFile(atPath: path, contents: data, attributes: nil)
}
return url
}
}
Usage:
if let url = URL.localURLForXCAsset(name: "MyIcon") {
// code
}