我可以从 XCAssets 包中获取 NSURL 吗?

Posted

技术标签:

【中文标题】我可以从 XCAssets 包中获取 NSURL 吗?【英文标题】:Can I get a NSURL from an XCAssets bundle? 【发布时间】:2014-02-14 01:17:25 【问题描述】:

我正在列出邮件中的附件。每个附件都有一个与之关联的 NSURL,表示附件数据的路径。对于非图像附件,我想加载预生成的图标缩略图来代替预览(即 excel 文档、PDF、word 等)。

我目前在我的项目中拥有这些图像,位于 XCAssets 包中。我可以使用[UIImage imageNamed:@"someName"] 联系他们。我似乎无法通过 NSBundle 的各种资源查找方法找到它们。 XCAssets 捆绑包是否会以某种方式更改我要查找的图标图像的文件名?

这是我目前正在使用的代码。路径每次都是零。在这种情况下我不需要使用 XCAssets 吗?

+ (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;

【问题讨论】:

【参考方案1】:

我想访问一些矢量资产以使用本地资源创建UNNotificationAttachment,所以我想出了这个帮助类。它基本上只是从资产中获取图像,将其数据保存到磁盘并返回文件 URL。我希望对某人有所帮助。

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
    


【讨论】:

谢谢你,你刚刚回答了我的赏金问题!! ***.com/questions/49360386/…【参考方案2】:

如果您的目标是 ios 7+,Xcode 5 现在会将资源转换为新的文件格式。所有资产的 1 个文件。这意味着您无法直接访问该文件。

如果您需要直接访问该文件,您可以将其作为正常图像包含在资产目录之外。

【讨论】:

这就是我害怕的。我无法找到任何直接文件来确认这一点,因此是这个问题。我可能只需要做出这个改变。谢谢。 我从未研究过这方面的细节,但[UIImage imageNamed:...] 仍然适用于资产包中的图像。 您实际上可以将文件从那里保存到您喜欢的任何目录。 :)【参考方案3】:

斯威夫特 5

作为 URL 扩展,它对我来说更有意义。

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
    

用法:

if let url = URL.localURLForXCAsset(name: "MyIcon") 
  // code

【讨论】:

【参考方案4】:

Swift 3Swift 2.3 版本的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
    


【讨论】:

【参考方案5】:

Swift 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

【讨论】:

以上是关于我可以从 XCAssets 包中获取 NSURL 吗?的主要内容,如果未能解决你的问题,请参考以下文章

从Images.xcassets加载图像

从 String 到 NSURL 的转换不断返回 nil

Images.xcassets 不包含在 .app 中

如何从 Xcassets 获取 iOS 版本的特定资产

如何在 OS X 上获取可移动卷的 NSURL 并在安装时发出通知?

从 Assets.xcassets 加载视频