查找自动调用函数的包

时间:2019-07-12 03:15:27

标签: swift bundle xcasset

我正在处理的项目最近由于无法控制的原因而被拆分为多个较小的项目。

我们在一个项目中提供了一些帮助程序方法来创建速记并键入安全的图像请求...其原因是在主题化方面具有灵活性。也许其中一个主题detailDisclosure与另一个主题不同。

语法看起来像这样

public extension UIImageView {
    convenience init(_ key: UIImage.Key) {
        self.init(image: UIImage(named: theme.imageName(for: key)))
    }
}

let imageView = UIImageView(.detailDisclosure)

它是姐妹函数

let image = UIImage(.detailDisclosure)

当所有图像和主题都位于同一位置时,这很简单。但是,现在我们有不同的项目,这些项目在不同的资产文件夹中具有不同的资产。

所以我要做的就是添加...

convenience init(_ key: UIImage.Key, in locality: AnyClass? = nil) {
    self.init(image: UIImageView.localImage(named: key.rawValue, in: locality))
}

// Currently assumes this method and default assets are in the main bundle by default 
fileprivate static func localImage(named name: String, in locality: AnyClass?) -> UIImage? {
    let bundle = (locality != nil) ? Bundle(for: locality!) : Bundle.main
    return UIImage(named: name, in: bundle, compatibleWith: nil)
}

let image = UIImage(.detailDisclosure, in: ThisProjectTheme.self)

ThisProjectTheme实际上可以是该捆绑软件中的任何类,从技术上讲,您也可以以这种方式转到另一个捆绑软件并共享其资源。

但是,从消费者的角度来看,这种额外的努力是我希望避免的事情,而且对于新来者来说,这也是非常危险的。

更好的情况是,除非该API的使用者指定了不同的locality,否则我们会自动找到它们的位置;而不是当前解决方案转到主捆绑包。

将来,大多数此类请求将来自拥有自己资产的项目。

我看过例如 file: String = #file

convenience init(_ key: UIImage.Key, file: String = #file, in locality: AnyClass? = nil)

显然我们可以破解它,但是我想知道是否有一种优雅的解决方案来获取发件人或与此相关的捆绑,而无需消费者隐式地将其发送给函数?

感谢您的时间

1 个答案:

答案 0 :(得分:1)

“从哪个捆绑中自动调用了一个功能”

听起来可能很吸引人,但您 完全 不希望这样。当您发现将某些代码从一个项目复制/粘贴到另一个项目中,从而使其行为有所不同时,那一刻就是丢掉大理石的那一刻。

相反,我认为整个方法都需要重新设计。例如,UIImage似乎是抽象的错误点。相反,我会使用类似这样的东西:

import UIKit

class ImageProvider {
    let bundle: Bundle

    init(bundle: Bundle) {
        self.bundle = bundle
    }

    init(forMainClass mainClass: AnyClass) {
        self.init(bundle: Bundle(for: mainClass)!)
    }

    func image(
        named: String,
        with configuration: UIImage.Configuration? = nil
    ) -> UIImage {
        return UIImage(named: name, in: self.bundle, with: configuration)?
    }
}

每个应用程序都将创建自己的ImageProvider,该应用程序将搜索其捆绑包中的资产。

这有几个主要优点:

  1. 可以轻松地将接口提取到协议中,并可以创建模拟实现以用于测试。
  2. 您只有一个进入图像系统的入口,可以处理缓存,主题化,调整大小等。
  3. 您可以将其扩展为将查询处理成多个包(“首先搜索我的应用程序包,否则,请尝试此框架的包”)
  4. 您可以扩展它以使用枚举来标识图像,而不是原始字符串。