【问题标题】:iOS: How to add Assets folder inside a Framework and how to access them in code?iOS:如何在框架内添加资产文件夹以及如何在代码中访问它们?
【发布时间】:2020-02-09 09:07:07
【问题描述】:

我创建了一个 iOS 应用并为其添加了一个框架。生成的框架没有像 generate Single View App 这样的资产文件夹。所以我在framework文件夹里面做了一个assets文件夹,拖拽到xcode,选择target作为我的framework。

我尝试使用该资产,但该资产未显示。可以告诉我如何正确地做到这一点吗?是否可以在框架内创建资产文件夹?

我对 iOS 非常陌生,因此非常感谢任何指导。提前致谢。

【问题讨论】:

    标签: ios swift ios-frameworks


    【解决方案1】:

    像往常一样通过New File...> Resources资产目录添加到框架目标,但要从此类资产中获取资源,它需要明确指定捆绑包,如下面的例子...

    假设ImageProvider在框架目标中,代码可能是

    public class ImageProvider {
        // convenient for specific image
        public static func picture() -> UIImage {
            return UIImage(named: "picture", in: Bundle(for: self), with: nil) ?? UIImage()
        }
    
        // for any image located in bundle where this class has built
        public static func image(named: String) -> UIImage? {
            return UIImage(named: named, in: Bundle(for: self), with: nil)
        }
    }
    

    当然你可以随便命名这样的类。

    【讨论】:

    • 即使我只访问同一框架内的资产,这也是真的吗?
    • 是的,因为默认情况下资源搜索在Bundle.main中执行。
    • 这是否意味着要访问资产,我现在必须随时随地以这种方式访问​​它?因为这个ImageProvider 类必须可用于我在项目中拥有的所有框架/模块。不是吗?
    • @ArchieG.Quiñones,简而言之 - 是的(适用于任何非主捆绑包、框架、插件等中的资产)。通过一些方便的示例查看更新的代码。
    【解决方案2】:

    我是这样做的。

    首先,您可以通过以下方式创建一个 Bundle 来保存您的资产(例如图片)。

    首先,创建一个新目标: 导航到 Xcode 主菜单,File => New => Target。然后选择“macOS选项卡” 从“框架和库”中选择“捆绑”。

    给它你想要的名字,然后点击完成。您应该会在项目文件夹中看到该捆绑包。

    ,Bundle构建设置的配置变化: 转到捆绑目标上的 Build Settings 并将 Base SDK 更改为 iOS。

    第三,添加图片: 直接将您的图像添加到 Bundle,无需添加资产文件夹。只需拖放即可。

    第四,构建捆绑包: 选择您的捆绑包作为目标,然后选择通用 iOS 设备并点击 Command + B

    第五,.bundle 将出现在您的项目文件夹下的产品文件夹中。右键单击它并在 Finder 中查看它,然后将其拖放到主项目文件夹中。

    最后,下面是我访问捆绑包中资产的方法。

    // Empty UIImage array to store the images in it.
    var images = [UIImage]()
    
    let fileManager = FileManager.default
    let bundleURL = Bundle.main.bundleURL
    let assetURL = bundleURL.appendingPathComponent("MyBundle.bundle") // Bundle URL
    do {
      let contents = try fileManager.contentsOfDirectory(at: assetURL,
     includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey],
     options: .skipsHiddenFiles)
      for item in contents { // item is the URL of everything in MyBundle imgs or otherwise.
    
          let image = UIImage(contentsOfFile: item.path) // Initializing an image
          images.append(image!) // Adding the image to the icons array
      }
    }
    catch let error as NSError {
      print(error)
    }
    
    

    您的包中将包含 .plist 文件,因此,我建议您通过一个简单的条件来处理此问题,以检查文件名是否为 Info.plist,不要从中创建图像。

    这是我以非常简单的方式处理它的方法。

        let fileManager = FileManager.default
        let bundleURL = Bundle.main.bundleURL
        let assetURL = bundleURL.appendingPathComponent("Glyphs.bundle")
        do {
          let contents = try fileManager.contentsOfDirectory(at: assetURL, includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey], options: .skipsHiddenFiles)
          for item in contents {
            let imageName = item.lastPathComponent
            if imageName != "Info.plist" {
              let image = UIImage(contentsOfFile: item.path)
              icons.append(image!)
            }
          }
        }
        catch {
          //print(error)
          showAlert(withTitle: "Error", message: "Can't get the icons.")
        }
    

    【讨论】:

    • 请注意,这种方法无法获得 Xcode 资产包的任何优点,Xcode 资产包允许您为不同的屏幕分辨率、设备和暗/亮模式轻松设置不同的图像。
    【解决方案3】:

    我遇到了同样的问题。 场景:

    1. 我们的框架将用于 iOS/OSX
    2. Framework 中有很多 PNG
    3. 我们希望在 iOSApp && MacOs 中使用 pngs
    4. 让我们假设框架项目和目标是“MyCustomFramework.framework”(通常是黄色图标..)已经在我们的应用程序中

    -

    func filePathInFrameworkBundle(name: String)->String{
    
        let myBundlePath  = Bundle.main.bundlePath
    
        #if  os(iOS)
    
        let inMyFW = myBundlePath +
            "/Frameworks" +
        "/MyCustomFramework.framework"
    
        #elseif os(OSX)
        let inMyFW = myBundlePath +
            "/Contents/Frameworks" +
            "/MyCustomFramework.framework" + "/Versions/A/Resources"
    
        #else
        #endif
    
        let pathInBundle = inMyFW+"/"+name
        return pathInBundle
    }
    

    现在您可以在通常的图像加载调用中使用此路径。

    【讨论】:

      【解决方案4】:

      对于 SwiftUI 使用:

      1. 将资产目录添加到您的框架项目(例如,“Media.xcassets”)。
      2. 添加资源,例如颜色集。假设您将颜色命名为“Thunder”。
      3. 在您的框架中创建一个名为“Color+Extensions.swift”(或任何您喜欢的文件)的文件。
      4. 在这个文件里面做:
          import SwiftUI
      
          private class LocalColor {
            // only to provide a Bundle reference
          }
      
          public extension Color {
              static var thunder: Color {
                  Color("Thunder", bundle: Bundle(for: LocalColor.self))
              }
          }
      

      我想这也适用于其他资产类型。

      在使用你的框架的项目中,一旦你为你的框架添加了import,你应该可以正常使用颜色了:

          Rectangle().foregroundColor(.thunder)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-14
        • 2021-06-26
        • 1970-01-01
        • 2016-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多