Shark 是一个 Swift 命令行工具,它可以为你的图片、颜色、Storyboard、字体和本地化生成类型安全的枚举。 Shark 支持为 Apple UI 框架 UIKit
、AppKit
和 SwiftUI
生成代码。
因为 Shark 读取你的 .xcodeproj
文件来查找这些资源,所以设置非常简单。
WWDC 2023 新闻 尽管 Shark 的部分功能被 Xcode 15 中新的 Color
和 Image
资源抄袭了(**sherlocked**),但它仍然不支持字体、Storyboard 和本地化。因此,我们将继续维护 Shark!
以下是一个为 UIKit
生成的 Shark.swift
文件的示例,以及它如何在代码库中使用
// Shark.swift
// Generated by Shark https://github.com/kaandedeoglu/Shark
import UIKit
// swiftlint:disable all
public enum Shark {
private static let bundle: Bundle = {
class Custom {}
return Bundle(for: Custom.self)
}()
public enum I {
public enum Button {
public static var profile: UIImage { return UIImage(named:"profile", in: bundle, compatibleWith: nil)! }
public static var cancel: UIImage { return UIImage(named:"cancel", in: bundle, compatibleWith: nil)! }
public static var user_avatar: UIImage { return UIImage(named:"user_avatar", in: bundle, compatibleWith: nil)! }
}
}
public enum C {
public static var blue1: UIColor { return UIColor(named: "blue1", in: bundle, compatibleWith: nil)! }
public static var blue2: UIColor { return UIColor(named: "blue2", in: bundle, compatibleWith: nil)! }
public static var gray1: UIColor { return UIColor(named: "gray1", in: bundle, compatibleWith: nil)! }
public static var gray2: UIColor { return UIColor(named: "gray2", in: bundle, compatibleWith: nil)! }
public static var green1: UIColor { return UIColor(named: "green1", in: bundle, compatibleWith: nil)! }
public static var green2: UIColor { return UIColor(named: "green2", in: bundle, compatibleWith: nil)! }
}
public enum F {
public static func gothamBold(ofSize size: CGFloat) -> UIFont { return UIFont(name: "Gotham-Bold", size: size)! }
public static func gothamMedium(ofSize size: CGFloat) -> UIFont { return UIFont(name: "Gotham-Medium", size: size)! }
public static func gothamRegular(ofSize size: CGFloat) -> UIFont { return UIFont(name: "Gotham-Regular", size: size)! }
}
public enum L {
public enum button {
/// Login
public static var login: String { return NSLocalizedString("button.login", bundle: bundle, comment: "") }
/// Logout
public static var logout: String { return NSLocalizedString("button.logout", bundle: bundle, comment: "") }
}
public enum login {
/// Please log in to continue
public static var title: String { return NSLocalizedString("login.title", bundle: bundle, comment: "") }
/// Skip login and continue
public static var skip: String { return NSLocalizedString("login.skip", bundle: bundle, comment: "") }
public enum error {
/// Login failed
public static var title: String { return NSLocalizedString("login.error.title", bundle: bundle, comment: "") }
/// Operation failed with error: %@
public static func message(_ value1: String) -> String {
return String(format: NSLocalizedString("login.error.message", bundle: bundle, comment: ""), value1)
}
}
}
}
}
// At the call site
imageView.image = Shark.I.Button.profile
label.font = Shark.F.gothamBold(ofSize: 16.0)
label.text = Shark.L.login.title
view.backgroundColor = Shark.C.green1
// You can also make it prettier with typealiases
typealias I = Shark.I
typealias C = Shark.C
typealias F = Shark.F
typealias L = Shark.L
imageView.image = I.Button.profile
label.font = F.gothamBold(ofSize: 16.0)
label.text = L.login.error.message("I disobeyed my masters")
view.backgroundColor = C.green1
有几点需要注意
首先,请查看 Xcode 中资源目录文件夹条目的检查器窗格的截图
如果你将图片和颜色资源放在文件夹中,Shark 将创建命名空间的 enum
– 前提是你已配置相应的 Xcode 设置 _Provides Namespace_(提供命名空间)。 如果你有深度嵌套的文件夹,Shark 将遵循每个文件夹的单独命名空间设置。
本地化总是使用分隔符进行命名空间。 目前,Shark 使用点符号 .
作为分隔符。 正如你所见,本地化键会递归地进行命名空间,直到我们到达最后一个组成部分。
brew install kaandedeoglu/formulae/shark
mint install kaandedeoglu/formulae/shark
克隆项目,然后执行
> swift build -c release
> cp ./build/release/Shark /usr/local/bin
然后,你可以通过执行以下操作来验证安装
> shark --help
向你的目标构建阶段添加一个新的 Run Script 阶段。 此构建阶段最好在 Compile Sources
阶段之前运行。 脚本正文应如下所示
if [ -x "$(command -v shark)" ]; then
shark $PROJECT_FILE_PATH $PROJECT_DIR/$PROJECT_NAME/
fi
if/fi
块确保 Shark 仅在当前机器上安装时运行。
构建你的项目。 你现在应该在你的项目文件夹中看到一个名为 Shark.swift
的文件。
将此文件添加到你的目标。 完成! 每次构建项目时,Shark.swift
都会更新。
或者,你可以执行以下操作
# Write to a specific file called MyAssets.swift
shark $PROJECT_FILE_PATH $PROJECT_DIR/$PROJECT_NAME/MyAssets.swift
# Write to a specific file in a different folder
shark $PROJECT_FILE_PATH $PROJECT_DIR/$PROJECT_NAME/Utility/MyAssets.swift
Shark 还接受以下命令行选项来配置行为
默认情况下,一切都在顶层枚举下,这个枚举的名字是 - 你猜对了 - Shark
。 你可以使用 --name
标志来更改它。
shark $PROJECT_FILE_PATH $PROJECT_DIR/$PROJECT_NAME --name Assets
默认情况下,Shark 将尝试查找英语本地化以生成本地化枚举。 如果你的项目中没有英文 .strings
文件,或者你希望 Shark 将其他本地化作为基础,你可以使用 --locale
标志指定语言代码。
# Use Spanish localizations for generation
shark $PROJECT_FILE_PATH $PROJECT_DIR/$PROJECT_NAME --locale es
如果你的 Xcode 项目有多个应用程序目标,你应该使用 --target
标志指定 Shark 应该查看哪一个。
shark $PROJECT_FILE_PATH $PROJECT_DIR/$PROJECT_NAME --target MyAppTarget
默认情况下,Shark 将创建所有属性,其可见性为 public
。 提交此选项以将其更改为例如 internal
。
默认情况下,Shark 为 UIKit
创建代码。 指定 --framework appkit
以创建 AppKit
的代码,并指定 --framework swiftui
以创建 SwiftUI
的代码。
Shark 将使用分隔符字符值分割本地化键,并创建嵌套的枚举,直到我们到达最后一个元素。 例如,以下行 login.button.positive = "Log in!";
和 login.button.negative = "Go back...";
将在顶级本地化枚举 L
中创建以下结构
public enum login {
public enum button {
public static var positive: String { return NSLocalizedString("login.button.positive") }
public static var negative: String { return NSLocalizedString("login.button.negative") }
}
}
默认情况下,分隔符是 .
,此选项仅接受单字符输入。
在顶级作用域中声明 I、C、F、L
枚举,而不是将它们嵌套在顶级 Shark
枚举中。
默认情况下,Shark 将处理它知道的所有资源文件。 如果你不希望这样做,你可以指定例外。 请注意,Shark 使用后缀匹配来识别要排除的文件。
将概述、示例用法和可用标志打印到控制台。
MIT 许可证 (MIT)
版权所有 (c) Kaan Dedeoglu, Dr. Michael 'Mickey' Lauer, 和贡献者。
特此授予任何人免费获得本软件及相关文档文件(“软件”)副本的许可,允许对软件进行处理,不受限制,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向提供软件的人员提供软件,但须遵守以下条件
上述版权声明和本许可声明应包含在所有副本或本软件的实质性部分中。
本软件按“原样”提供,不提供任何形式的明示或暗示保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。 在任何情况下,作者或版权持有者均不对任何索赔、损害或其他责任负责,无论是在合同、侵权或其他方面,由软件或软件的使用或其他交易引起、产生或与之相关。