iOS 成长快线

用SwiftGen管理UIImage等的String-based

2017-12-08  本文已影响0人  hanson21

问题现状

平时我们使用UIImage,UIFont,UIColor会遇到很多String-based的接口方法,比如常用的UIImage:

let testImage = UIImage(named: "test")

对于上面的代码,如果我们把 test 拼写错了,Xcode 并不会给出提示,只有当我们运行的时候才会收到报错,这样维护起来是有一定成本的。

代码解决

我们可以用类似如下的代码来解决这个问题:

import UIKit.UIImage

struct ImageAssets {
    fileprivate var name: String
    var image: UIImage {
        let image = UIImage(named: name)
        guard let result = image else { fatalError("Unable to load image named \(name).") }
        return result
    }
}

enum Assets {
    enum AppLogo {
        static let appLogo = ImageAssets(name: "appLogo")
        static let grayLogo = ImageAssets(name: "gray_logo")
    }
    enum Arrow {
        static let arrowBlue = ImageAssets(name: "arrow_blue")
        static let arrowBrown = ImageAssets(name: "arrow_brown")
    }
    // ....
}

extension UIImage {
    convenience init!(asset: ImageAssets) {
        self.init(named: asset.name)
    }
}

利用上面的代码,我们在新建 UIImage 的时候就不需要去想图片的名字了,而且 Xcode 还会有代码提示:

let logo = Asset.AppLogo.appLogo.image
let grayLogo = UIImage(asset: Asset.AppLogo.grayLogo)

存在问题

虽然这种方法在调用的时候简单又安全了,但是项目中的图片往往比较多,如果手动编写维护那段代码也是需要不少精力,而且不能保证后续不会添加新的图片,这样每次都要去维护那段代码不免有些反人类。
那么现在就要介绍这个开源项目--- SwiftGen了!

SwiftGen is a tool to auto-generate Swift code for resources of your projects, to make them type-safe to use.

利用 SwiftGen 可以帮我们生成这类的代码,但是 SwiftGen 默认生成的代码样式有时候并不是我们想要的,而且默认生成还会有针对 macOS 上的代码,比较好的是 SwiftGen 提供了模板的功能,我们可以按自己的需要来修改模板。

集成 SwiftGen 在项目中

SwiftGen 提供了好几种的集成方式,我这里只介绍我自己比较喜欢的方式:就是通过下载它的 Zip 文件解压到项目的目录中,然后通过添加 Run Script 来进行管理。这样可以基本做到不用操心代码。

1.修改模板

2.建立RunScript

下面是生成的 ImageAsset.swift 的代码:

  // ImageAsset.swift
  // Generated using SwiftGen, using my-templete created by Hanson
  
  import UIKit.UIImage
  
  typealias Image = UIImage
  
  @available(*, deprecated, renamed: "ImageAsset")
  typealias AssetType = ImageAsset
  
  struct ImageAsset {
    fileprivate var name: String
  
    var image: Image {
      let bundle = Bundle(for: BundleToken.self)
      let image = Image(named: name, in: bundle, compatibleWith: nil)
      guard let result = image else { fatalError("Unable to load image named \(name).") }
      return result
    }
  }
  
  enum Asset {
    static let arrowBlue = ImageAsset(name: "arrow_blue")
    static let arrowBrown = ImageAsset(name: "arrow_brown")
    static let iconLeftBack = ImageAsset(name: "icon_left_back")
    static let startLogo = ImageAsset(name: "start_logo")
  }

  extension Image {
    convenience init!(asset: ImageAsset) {
      let bundle = Bundle(for: BundleToken.self)
      self.init(named: asset.name, in: bundle, compatibleWith: nil)
    }
  }
 
  private final class BundleToken {}

结语

这里只是利用了 SwiftGen 对于 Image 的部分。它还有其它的关于 StringStroyBoardFont等等的代码生成。原理基本相同,靠大家按需研究啦。

到我的博客阅读:myhanson.com
本文Demo:SwiftGenExample

Contact

我的微博:汉森hs
我的Github: zyphs21
我的博客: myhanson.com
我的公众号:HansonTalk

上一篇 下一篇

猜你喜欢

热点阅读