¿Puedo obtener un NSURL de un paquete XCAssets?
Frecuentes
Visto 26,738 equipos
33
I'm in a situation where I am listing attachments from a message. Each attachment has a NSURL associated with it that represents a path to the attachment data. In the case of non-image attachments I want to load pre-generated icon thumbnails in the place of a preview (i.e. excel documents, PDF, word, etc).
I currently have these images in my project, within an XCAssets bundle. I can get at them using [UIImage imageNamed:@"someName"]
. I cannot seem to get at them via NSBundle's various resource lookup methods. Does the XCAssets bundle somehow change the filenames of the icon images I'm looking for?
Here's the code I'm currently working with. Path is nil every time. Do I need to not use XCAssets in this case?
+ (NSURL *)mediaURLWithMessage:(SRMediaMessage*)message
{
NSURL *url = message.mediaURL;
// if this is an image URL or non-existant, there is no work left to do, return it.
if (!url || (message.secureFile.secureFileMimeType & SRSecureFileMimeTypeImage))
return url;
NSString *filename = @"unknown";
switch (message.secureFile.secureFileMimeType)
{
case SRSecureFileMimeTypeDOC:
filename = @"doc";
break;
case SRSecureFileMimeTypePPT:
filename = @"ppt";
break;
case SRSecureFileMimeTypePDF:
filename = @"pdf";
break;
case SRSecureFileMimeTypeXLS:
filename = @"exl";
break;
case SRSecureFileMimeTypeCSV:
filename = @"csv";
break;
case SRSecureFileMimeTypeTXT:
filename = @"txt";
break;
case SRSecureFileMimeTypeRTX:
filename = @"rtf";
break;
default:
case SRSecureFileMimeTypeMP4:
// unknown icon for now.
break;
// unused but available:
// @"ilife"
}
NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
if (path)
url = [NSURL fileURLWithPath:path];
return url;
}
5 Respuestas
22
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
}
}
Respondido el 30 de Septiembre de 16 a las 09:09
14
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.
Respondido 14 Feb 14, 01:02
That's what I was afraid of. I haven't been able to find any direct documentation to confirm this, thus the question. I may just have to make this change. Thanks. - astuto
I've never looked into the details of that, but [UIImage imageNamed:...]
still works with images in an asset bundle. - Holly
And you can actually save file from there to any directory you like. :) - Sin lego
13
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
}
}
Uso:
if let url = URL.localURLForXCAsset(name: "MyIcon") {
// code
}
Respondido 26 Feb 21, 19:02
9
Swift 3 y Swift 2.3 versiones de the answer by @tadija:
Swift 3:
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")
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
}
}
Swift 2.3:
import UIKit
class AssetExtractor {
static func createLocalUrl(forImageNamed name: String) -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let cacheDirectory = fileManager.URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask)[0]
guard
let url = cacheDirectory.URLByAppendingPathComponent("\(name).png"),
let path = url.path
else { return nil }
guard fileManager.fileExistsAtPath(path) else {
guard
let image = UIImage(named: name),
let data = UIImagePNGRepresentation(image)
else { return nil }
fileManager.createFileAtPath(path, contents: data, attributes: nil)
return url
}
return url
}
}
contestado el 23 de mayo de 17 a las 13:05
1
Rápido 3.x
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")
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
}
Respondido el 17 de Septiembre de 17 a las 13:09
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas ios objective-c cocoa-touch or haz tu propia pregunta.
Thank you man, you just answered my bounty question!! stackoverflow.com/questions/49360386/… - usuario7219266