SwiftGen
SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them type-safe to use.
![]() | Then generate constants for: |
There are multiple benefits in using this:
- Avoid any risk of typo when using a String
- Free auto-completion
- Avoid the risk of using a non-existing asset name
- All this will be ensured by the compiler and thus avoid the risk of crashing at runtime.
Also, it's fully customizable thanks to Stencil templates, so even if it comes with predefined templates, you can make your own to generate whatever code fits your needs and your guidelines!
Installation
There are multiple possibilities to install SwiftGen on your machine or in your project, depending on your preferences and needs:
Download the ZIP for the latest release
- Go to the GitHub page for the latest release
- Download the
swiftgen-x.y.z.zip
file associated with that release - Extract the content of the zip archive in your project directory
We recommend that you unarchive the ZIP inside your project directory and commit its content to git. This way, all coworkers will use the same version of SwiftGen for this project.
If you unarchived the ZIP file in a folder e.g. called swiftgen
at the root of your project directory, you can then invoke SwiftGen in your Script Build Phase using:
"${PROJECT_DIR}/swiftgen/bin/swiftgen" …
Via CocoaPods
If you're using CocoaPods, simply add pod 'SwiftGen', '~> 6.0'
to your Podfile
.
Then execute pod install --repo-update
(or pod update SwiftGen
if you want to update an existing SwiftGen installation) to download and install the SwiftGen
binaries and dependencies in Pods/SwiftGen/bin/swiftgen
next to your project.
Given that you can specify an exact version for SwiftGen
in your Podfile
, this allows you to ensure all coworkers will use the same version of SwiftGen for this project.
You can then invoke SwiftGen in your Script Build Phase using:
if [[ -f "${PODS_ROOT}/SwiftGen/bin/swiftgen" ]]; then
"${PODS_ROOT}/SwiftGen/bin/swiftgen" …
else
echo "warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it."
fi
Similarly, be sure to use
Pods/SwiftGen/bin/swiftgen
instead of justswiftgen
where we mention commands withswiftgen
in the rest of the documentation.
Note: SwiftGen isn't really a pod, as it's not a library your code will depend on at runtime; so the installation via CocoaPods is just a trick that installs the SwiftGen binaries in the Pods/ folder, but you won't see any swift files in the Pods/SwiftGen group in your Xcode's Pods.xcodeproj. That's normal; the SwiftGen binary is still present in that folder in the Finder.
Via Homebrew (system-wide installation)
To install SwiftGen via Homebrew, simply use:
$ brew update
$ brew install swiftgen
This will install SwiftGen system-wide. The same version of SwiftGen will be used for all projects on that machine, and you should make sure all your coworkers have the same version of SwiftGen installed on their machine too.
You can then invoke swiftgen
directly in your Script Build Phase (as it will be in your $PATH
already):
swiftgen …
Via Mint (system-wide installation)
❗️SwiftGen 6.0 or higher only.
To install SwiftGen via Mint, simply use:
$ mint install SwiftGen/SwiftGen
Compile from source (only recommended if you need features from the `stable` branch or want to test a PR)
This solution is when you want to build and install the latest version from stable
and have access to features which might not have been released yet.
- If you have
homebrew
installed, you can use the following command to build and install the latest commit:
brew install swiftgen --HEAD
- Alternatively, you can clone the repository and use
rake cli:install
to build the tool and install it from any branch, which could be useful to test SwiftGen in a fork or a Pull Request branch.
Some Ruby tools are used in the build process, and the system Ruby works well if you are running a recent macOS. However, if you are using rbenv
you can run rbenv install
to make sure you have a matching version of Ruby installed.
Then install the Ruby Gems:
# Install bundle if it isn't installed
gem install bundle
# Install the Ruby gems from Gemfile
bundle install
You can now install to the default locations (no parameter) or to custom locations:
# Binary is installed in `./build/swiftgen/bin`, frameworks in `./build/swiftgen/lib` and templates in `./build/swiftgen/templates`
$ rake cli:install
# - OR -
# Binary will be installed in `~/swiftgen/bin`, frameworks in `~/swiftgen/fmk` and templates in `~/swiftgen/tpl`
$ rake cli:install[~/swiftgen/bin,~/swiftgen/fmk,~/swiftgen/tpl]
You can then invoke SwiftGen using the path to the binary where you installed it:
~/swiftgen/bin/swiftgen …
Or add the path to the bin
folder to your $PATH
and invoke swiftgen
directly.
Known Installation Issues On macOS Before 10.14.4
Starting with SwiftGen 6.2.1, if you get an error similar to dyld: Symbol not found: _$s11SubSequenceSlTl
when running SwiftGen, you'll need to install the Swift 5 Runtime Support for Command Line Tools.
Alternatively, you can:
- Update to macOS 10.14.4 or later
- Install Xcode 10.2 or later at
/Applications/Xcode.app
- Rebuild SwiftGen from source using Xcode 10.2 or later
Configuration File
❗️ If you're migrating from older SwiftGen versions, don't forget to read the Migration Guide.
SwiftGen is provided as a single command-line tool which uses a configuration file to define the various parsers to run (depending on the type of input files you need to parse) and their parameters.
To create a sample configuration file as a starting point to adapt to your needs, run swiftgen config init
.
Each parser described in the configuration file (strings
, fonts
, ib
, …) typically corresponds to a type of input resources to parse (strings files, IB files, Font files, JSON files, …), allowing you to generate constants for each types of those input files.
To use SwiftGen, simply create a swiftgen.yml
YAML file (either manually or using swiftgen config init
) then edit it to adapt to your project. The config file should list all the parsers to invoke, and for each parser, the list of inputs/outputs/templates/parameters to use for it.
For example:
strings:
inputs: Resources/Base.lproj
outputs:
- templateName: structured-swift5
output: Generated/Strings.swift
xcassets:
inputs:
- Resources/Images.xcassets
- Resources/MoreImages.xcassets
- Resources/Colors.xcassets
outputs:
- templateName: swift5
output: Generated/Assets.swift
Then you just have to invoke swiftgen config run
, or even just swiftgen
for short, and it will execute what's described in the configuration file.
The dedicated documentation explains the syntax and possibilities in details – like how to pass custom parameters to your templates, use swiftgen config lint
to validate your config file, how to use alternate config files, and other tips.
There are also additional subcommands you can invoke from the command line to manage and configure SwiftGen:
- The
swiftgen config
subcommand to help you with the configuration file, especiallyswiftgen config init
to create a starting point for your config andswiftgen config lint
to validate that your Config file is valid and has no errors - The
swiftgen template
subcommands to help you print, duplicate, find and manage templates bundled with SwiftGen
Lastly, you can use --help
on swiftgen
or one of its subcommand to see the detailed usage.
Directly invoking a parser without a config file
While we highly recommend the use a configuration file for performance reasons (especially if you have multiple outputs, but also because it's more flexible), it's also possible to directly invoke the available parsers individually using swiftgen run
:
swiftgen run colors [OPTIONS] DIRORFILE1 …
swiftgen run coredata [OPTIONS] DIRORFILE1 …
swiftgen run fonts [OPTIONS] DIRORFILE1 …
swiftgen run ib [OPTIONS] DIRORFILE1 …
swiftgen run json [OPTIONS] DIRORFILE1 …
swiftgen run plist [OPTIONS] DIRORFILE1 …
swiftgen run strings [OPTIONS] DIRORFILE1 …
swiftgen run xcassets [OPTIONS] DIRORFILE1 …
swiftgen run yaml [OPTIONS] DIRORFILE1 …
One rare cases where this might be useful — as opposed to using a config file — is if you are working on a custom template and want to quickly test the specific parser you're working on at each iteration/version of your custom template, until you're happy with it.
Each parser command generally accepts the same options and syntax, and they mirror the options and parameters from the configuration file:
--output FILE
or-o FILE
: set the file where to write the generated code. If omitted, the generated code will be printed onstdout
.--templateName NAME
or-n NAME
: define the Stencil template to use (by name, see here for more info) to generate the output.--templatePath PATH
or-p PATH
: define the Stencil template to use, using a full path.- Note: you should specify one and only one template when invoking SwiftGen. You have to use either
-t
or-p
but should not use both at the same time (it wouldn't make sense anyway and you'll get an error if you try) --filter REGEX
or-f REGEX
: the filter to apply to each input path. Filters are applied to actual (relative) paths, not just the filename. Each command has a default filter that you can override with this option.- Note: use
.+
to match multiple characters (at least one), and don't forget to escape the dot (\.
) if you want to match a literal dot like for an extension. Add$
at the end to ensure the path ends with the extension you want. Regular expressions will be case sensitive by default, and not anchored to the start/end of a path. For example, use.+\.xib$
to match files with a.xib
extension. Use a tool such as RegExr to ensure you're using a valid regular expression. - Each command supports multiple input files (or directories where applicable).
- You can always use the
--help
flag to see what options a command accept, e.g.swiftgen run xcassets --help
.
Choosing your template
SwiftGen is based on templates (it uses Stencil as its template engine). This means that you can choose the template that fits the Swift version you're using — and also the one that best fits your preferences — to adapt the generated code to your own conventions and Swift version.
Bundled templates vs. Custom ones
SwiftGen comes bundled with some templates for each of the parsers (colors
, coredata
, fonts
, ib
, json
, plist
, strings
, xcassets
, yaml
), which will fit most needs; simply use the templateName
output option to specify the name of the template to use. But you can also create your own templates if the bundled ones don't suit your coding conventions or needs: just store them anywhere (like in your project repository) and use the templatePath
output option instead of templateName
, to specify their path.
💡 You can use the swiftgen template list
command to list all the available bundled templates for each parser, and use swiftgen template cat
to show a template's content and duplicate it to create your own variation.
For more information about how to create your own templates, see the dedicated documentation.
Templates bundled with SwiftGen:
As explained above, you can use swiftgen template list
to list all templates bundled with SwiftGen. For most SwiftGen parsers, we provide, among others:
- A
swift4
template, compatible with Swift 4 - A
swift5
template, compatible with Swift 5 - Other variants, like
flat-swift4/5
andstructured-swift4/5
templates for Strings, etc.
You can find the documentation for each bundled template here in the repo, with documentation organized as one folder per SwiftGen parser, then one MarkDown file per template. You can also use swiftgen template doc
to open that documentation page in your browser directly from your terminal.
Each MarkDown file documents the Swift Version it's aimed for, the use case for that template (in which cases you might favor that template over others), the available parameters to customize it on invocation (using the params:
key in your config file), and some code examples.
Don't hesitate to make PRs to share your improvements suggestions on the bundled templates 😉
Additional documentation
Playground
The SwiftGen.playground
available in this repository will allow you to play with the code that the tool typically generates, and see some examples of how you can take advantage of it.
This allows you to have a quick look at how typical code generated by SwiftGen looks like, and how you will then use the generated constants in your code.
Dedicated Documentation in Markdown
There is a lot of documentation in the form of Markdown files in this repository, and in the related StencilSwiftKit repository as well.
Be sure to check the "Documentation" folder of each repository.
Especially, in addition to the previously mentioned Migration Guide and Configuration File documentation, the Documentation/
folder in the SwiftGen repository also includes:
- A
templates
subdirectory that details the documentation for each of the templates bundled with SwiftGen (when to use each template, what the output will look like, and custom parameters to adjust them, …) - A
SwiftGenKit Contexts
subdirectory that details the structure of the "Stencil Contexts", i.e. the Dictionary/YAML representation resulting of parsing your input files. This documentation is useful for people wanting to write their own templates, so that they know the structure and various keys available when writing their template, to construct the wanted generated output accordingly. - Various articles to provide best practices & tips on how to better take advantage of SwiftGen in your projects:
- Integrate SwiftGen in your Xcode project — so it rebuilds the constants every time you build
- Configure SwiftLint to help your developers use constants generated by SwiftGen
- Create a custom template, and watch a folder to auto-regenerate an output every time you save the template you're working on
- …and more
Tutorials
You can also find other help & tutorial material on the internet, like this classroom about Code Generation I gave at FrenchKit in Sept'17 — and its wiki detailing a step-by-step tutorial about installing and using SwiftGen (and Sourcery too)
Available Parsers
Asset Catalog
xcassets:
inputs: /dir/to/search/for/imageset/assets
outputs:
templateName: swift5
output: Assets.swift
This will generate an enum Asset
with one static let
per asset (image set, color set, data set, …) in your assets catalog, so that you can use them as constants.
Example of code generated by the bundled template
internal enum Asset {
internal enum Files {
internal static let data = DataAsset(value: "Data")
internal static let readme = DataAsset(value: "README")
}
internal enum Food {
internal enum Exotic {
internal static let banana = ImageAsset(value: "Exotic/Banana")
internal static let mango = ImageAsset(value: "Exotic/Mango")
}
internal static let `private` = ImageAsset(value: "private")
}
internal enum Styles {
internal enum Vengo {
internal static let primary = ColorAsset(value: "Vengo/Primary")
internal static let tint = ColorAsset(value: "Vengo/Tint")
}
}
internal enum Targets {
internal static let bottles = ARResourceGroupAsset(name: "Bottles")
internal static let paintings = ARResourceGroupAsset(name: "Paintings")
}
}
Usage Example
// You can create new images by referring to the enum instance and calling `.image` on it:
let bananaImage = Asset.Exotic.banana.image
let privateImage = Asset.private.image
// You can create colors by referring to the enum instance and calling `.color` on it:
let primaryColor = Asset.Styles.Vengo.primary.color
let tintColor = Asset.Styles.Vengo.tint.color
// You can create data items by referring to the enum instance and calling `.data` on it:
let data = Asset.data.data
let readme = Asset.readme.data
// you can load an AR resource group's items using:
let bottles = Asset.Targets.bottles.referenceObjects
let paintings = Asset.Targets.paintings.referenceImages
Colors
❗️ We recommend to define your colors in your Assets Catalogs and use the
xcassets
parser (see above) to generate color constants, instead of using thiscolors
parser described below.
Thecolors
parser below is mainly useful if you support older versions of iOS where colors can't be defined in Asset Catalogs, or if you want to use Android'scolors.xml
files as input.
colors:
inputs: /path/to/colors-file.txt
outputs:
templateName: swift5
output: Colors.swift
This will generate a enum ColorName
with one static let
per color listed in the text file passed as argument.
The input file is expected to be either:
- a plain text file, with one line per color to register, each line being composed by the Name to give to the color, followed by ":", followed by the Hex representation of the color (like
rrggbb
orrrggbbaa
, optionally prefixed by#
or0x
) or the name of another color in the file. Whitespaces are ignored. - a JSON file, representing a dictionary of names -> values, each value being the hex representation of the color
- a XML file, expected to be the same format as the Android colors.xml files, containing tags
<color name="AColorName">AColorHexRepresentation</color>
- a
*.clr
file used by Apple's Color Palettes.
For example you can use this command to generate colors from one of your system color lists:
colors:
inputs: ~/Library/Colors/MyColors.clr
outputs:
templateName: swift5
output: Colors.swift
Generated code will look the same as if you'd use a text file.
Example of code generated by the bundled template
Given the following colors.txt
file:
Cyan-Color : 0xff66ccff
ArticleTitle : #33fe66
ArticleBody : 339666
ArticleFootnote : ff66ccff
Translucent : ffffffcc
The generated code will look like this:
internal struct ColorName {
internal let rgbaValue: UInt32
internal var color: Color { return Color(named: self) }
/// <span style="display:block;width:3em;height:2em;border:1px solid black;background:#339666"></span>
/// Alpha: 100% <br/> (0x339666ff)
internal static let articleBody = ColorName(rgbaValue: 0x339666ff)
/// <span style="display:block;width:3em;height:2em;border:1px solid black;background:#ff66cc"></span>
/// Alpha: 100% <br/> (0xff66ccff)
internal static let articleFootnote = ColorName(rgbaValue: 0xff66ccff)
...
}
Usage Example
// You can create colors with the convenience constructor like this:
let title = UIColor(named: .articleBody) // iOS
let footnote = NSColor(named: .articleFootnote) // macOS
// Or as an alternative, you can refer to enum instance and call .color on it:
let sameTitle = ColorName.articleBody.color
let sameFootnote = ColorName.articleFootnote.color
This way, no need to enter the color red, green, blue, alpha values each time and create ugly constants in the global namespace for them.
Core Data
coredata:
inputs: /path/to/model.xcdatamodeld
outputs:
templateName: swift5
output: CoreData.swift
This will parse the specified core data model(s), generate a class for each entity in your model containing all the attributes, and a few extensions if needed for relationships and predefined fetch requests.
Example of code generated by the bundled template
internal class MainEntity: NSManagedObject {
internal class var entityName: String {
return "MainEntity"
}
internal class func entity(in managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: entityName, in: managedObjectContext)
}
@nonobjc internal class func makeFetchRequest() -> NSFetchRequest<MainEntity> {
return NSFetchRequest<MainEntity>(entityName: entityName)
}
@NSManaged internal var attributedString: NSAttributedString?
@NSManaged internal var binaryData: Data?
@NSManaged internal var boolean: Bool
@NSManaged internal var date: Date?
@NSManaged internal var float: Float
@NSManaged internal var int64: Int64
internal var integerEnum: IntegerEnum {
get {
let key = "integerEnum"
willAccessValue(forKey: key)
defer { didAccessValue(forKey: key) }
guard let value = primitiveValue(forKey: key) as? IntegerEnum.RawValue,
let result = IntegerEnum(rawValue: value) else {
fatalError("Could not convert value for key '\(key)' to type 'IntegerEnum'")
}
return result
}
set {
let key = "integerEnum"
willChangeValue(forKey: key)
defer { didChangeValue(forKey: key) }
setPrimitiveValue(newValue.rawValue, forKey: key)
}
}
@NSManaged internal var manyToMany: Set<SecondaryEntity>
}
// MARK: Relationship ManyToMany
extension MainEntity {
@objc(addManyToManyObject:)
@NSManaged public func addToManyToMany(_ value: SecondaryEntity)
@objc(removeManyToManyObject:)
@NSManaged public func removeFromManyToMany(_ value: SecondaryEntity)
@objc(addManyToMany:)
@NSManaged public func addToManyToMany(_ values: Set<SecondaryEntity>)
@objc(removeManyToMany:)
@NSManaged public func removeFromManyToMany(_ values: Set<SecondaryEntity>)
}
Usage Example
// Fetch all the instances of MainEntity
let request = MainEntity.makeFetchRequest()
let mainItems = try myContext.execute(request)
// Type-safe relationships: `relatedItem` will be a `SecondaryEntity?` in this case
let relatedItem = myMainItem.manyToMany.first
Fonts
fonts:
inputs: /path/to/font/dir
outputs:
templateName: swift5
output: Fonts.swift
This will recursively go through the specified directory, finding any typeface files (TTF, OTF, …), defining a struct FontFamily
for each family, and an enum nested under that family that will represent the font styles.
Example of code generated by the bundled template
internal enum FontFamily {
internal enum SFNSDisplay: String, FontConvertible {
internal static let regular = FontConvertible(name: ".SFNSDisplay-Regular", family: ".SF NS Display", path: "SFNSDisplay-Regular.otf")
}
internal enum ZapfDingbats: String, FontConvertible {
internal static let regular = FontConvertible(name: "ZapfDingbatsITC", family: "Zapf Dingbats", path: "ZapfDingbats.ttf")
}
}
Usage Example
// You can create fonts with the convenience constructor like this:
let displayRegular = UIFont(font: FontFamily.SFNSDisplay.regular, size: 20.0) // iOS
let dingbats = NSFont(font: FontFamily.ZapfDingbats.regular, size: 20.0) // macOS
// Or as an alternative, you can refer to enum instance and call .font on it:
let sameDisplayRegular = FontFamily.SFNSDisplay.regular.font(size: 20.0)
let sameDingbats = FontFamily.ZapfDingbats.regular.font(size: 20.0)
Interface Builder
ib:
inputs: /dir/to/search/for/storyboards
outputs:
- templateName: scenes-swift5
output: Storyboard Scenes.swift
- templateName: segues-swift5
output: Storyboard Segues.swift
This will generate an enum
for each of your NSStoryboard
/UIStoryboard
, with respectively one static let
per storyboard scene or segue.
Example of code generated by the bundled template
The generated code will look like this:
// output from the scenes template
internal enum StoryboardScene {
internal enum Dependency: StoryboardType {
internal static let storyboardName = "Dependency"
internal static let dependent = SceneType<UIViewController>(storyboard: Dependency.self, identifier: "Dependent")
}
internal enum Message: StoryboardType {
internal static let storyboardName = "Message"
internal static let messagesList = SceneType<UITableViewController>(storyboard: Message.self, identifier: "MessagesList")
}
}
// output from the segues template
internal enum StoryboardSegue {
internal enum Message: String, SegueType {
case customBack = "CustomBack"
case embed = "Embed"
case nonCustom = "NonCustom"
case showNavCtrl = "Show-NavCtrl"
}
}
Usage Example
// You can instantiate scenes using the `instantiate` method:
let vc = StoryboardScene.Dependency.dependent.instantiate()
// You can perform segues using:
vc.perform(segue: StoryboardSegue.Message.embed)
// or match them (in prepareForSegue):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch StoryboardSegue.Message(segue) {
case .embed?:
// Prepare for your custom segue transition, passing information to the destionation VC
case .customBack?:
// Prepare for your custom segue transition, passing information to the destionation VC
default:
// Other segues from other scenes, not handled by this VC
break
}
}
JSON and YAML
json:
inputs: /path/to/json/dir-or-file
outputs:
templateName: runtime-swift5
output: JSON.swift
yaml:
inputs: /path/to/yaml/dir-or-file
outputs:
templateName: inline-swift5
output: YAML.swift
This will parse the given file, or when given a directory, recursively search for JSON and YAML files. It will define an enum
for each file (and documents in a file where needed), and type-safe constants for the content of the file.
Unlike other parsers, this one is intended to allow you to use more custom inputs (as the formats are quite open to your needs) to generate your code. This means that for these parsers (and the plist
one), you'll probably be more likely to use custom templates to generate code properly adapted/tuned to your inputs, rather than using the bundled templates. To read more about writing your own custom templates, see see the dedicated documentation.
Example of code generated by the bundled template
internal enum JSONFiles {
internal enum Info {
private static let _document = JSONDocument(path: "info.json")
internal static let key1: String = _document["key1"]
internal static let key2: String = _document["key2"]
internal static let key3: [String: Any] = _document["key3"]
}
internal enum Sequence {
internal static let items: [Int] = objectFromJSON(at: "sequence.json")
}
}
Usage Example
// This will be a dictionary
let foo = JSONFiles.Info.key3
// This will be an [Int]
let bar = JSONFiles.Sequence.items
Plists
plist:
inputs: /path/to/plist/dir-or-file
outputs:
templateName: runtime-swift5
output: Plist.swift
This will parse the given file, or when given a directory, recursively search for Plist files. It will define an enum
for each file (and documents in a file where needed), and type-safe constants for the content of the file.
Unlike other parsers, this one is intended to allow you to use more custom inputs (as the format is quite open to your needs) to generate your code. This means that for this parser (and the json
and yaml
ones), you'll probably be more likely to use custom templates to generate code properly adapted/tuned to your inputs, rather than using the bundled templates. To read more about writing your own custom templates, see see the dedicated documentation.
Example of code generated by the bundled template
internal enum PlistFiles {
internal enum Test {
internal static let items: [String] = arrayFromPlist(at: "array.plist")
}
internal enum Stuff {
private static let _document = PlistDocument(path: "dictionary.plist")
internal static let key1: Int = _document["key1"]
internal static let key2: [String: Any] = _document["key2"]
}
}
Usage Example
// This will be an array
let foo = PlistFiles.Test.items
// This will be an Int
let bar = PlistFiles.Stuff.key1
Strings
strings:
inputs: /path/to/language.lproj
outputs:
templateName: structured-swift5
output: Strings.swift
This will generate a Swift enum L10n
that will map all your Localizable.strings
and Localizable.stringsdict
(or other tables) keys to a static let
constant. And if it detects placeholders like %@
,%d
,%f
, it will generate a static func
with the proper argument types instead, to provide type-safe formatting.
Note that all dots within the key names are converted to dots in code (by using nested enums). You can provide a different separator than
.
to split key names into substructures by using a parser option – see the parser documentation.
Example of code generated by the structured bundled template
Given the following Localizable.strings
file:
"alert_title" = "Title of the alert";
"alert_message" = "Some alert body there";
"bananas.owner" = "Those %d bananas belong to %@.";
And the following Localizable.stringsdict
file:
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>apples.count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@apples@</string>
<key>apples</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>You have no apples</string>
<key>one</key>
<string>You have one apple</string>
<key>other</key>
<string>You have %d apples. Wow that is a lot!</string>
</dict>
</dict>
</dict>
</plist>
Reminder: Don't forget to end each line in your
*.strings
files with a semicolon;
! Now that in Swift code we don't need semi-colons, it's easy to forget it's still required by theLocalizable.strings
file format 😉
The generated code will contain this:
internal enum L10n {
/// Some alert body there
internal static let alertMessage = L10n.tr("alert_message")
/// Title of the alert
internal static let alertTitle = L10n.tr("alert_title")
internal enum Apples {
/// Plural format key: "%#@apples@"
internal static func count(_ p1: Int) -> String {
return L10n.tr("apples.count", p1)
}
}
internal enum Bananas {
/// Those %d bananas belong to %@.
internal static func owner(_ p1: Int, _ p2: Any) -> String {
return L10n.tr("bananas.owner", p1, String(describing: p2))
}
}
}
Note that if the same key is present in both the .strings
and the .stringsdict
files, SwiftGen will only consider the one in the .stringsdict
file, as that's also how Foundation behaves at runtime.
Usage Example
Once the code has been generated by the script, you can use it this way in your Swift code:
// Simple strings
let message = L10n.alertMessage
let title = L10n.alertTitle
// with parameters, note that each argument needs to be of the correct type
let apples = L10n.Apples.count(3)
let bananas = L10n.Bananas.owner(5, "Olivier")
Flat Strings Support
SwiftGen also has a template to support flat strings files (i.e. without splitting the keys in substructures using "dot syntax"). The advantage is that your keys won't be mangled in any way; the disadvantage is that auto-completion won't be as nice.
Example of code generated by the flat bundled template
internal enum L10n {
/// Some alert body there
internal static let alertMessage = L10n.tr("Localizable", "alert__message")
/// Title of the alert
internal static let alertTitle = L10n.tr("Localizable", "alert__title")
/// Plural format key: "%#@apples@"
internal static func applesCount(_ p1: Int) -> String {
return L10n.tr("Localizable", "apples.count", p1)
}
/// Those %d bananas belong to %@.
internal static func bananasOwner(_ p1: Int, _ p2: Any) -> String {
return L10n.tr("Localizable", "bananas.owner", p1, String(describing: p2))
}
}
Given the same Localizable.strings
and Localizable.stringsdict
as above the usage will now be:
// Simple strings
let message = L10n.alertMessage
let title = L10n.alertTitle
// with parameters, note that each argument needs to be of the correct type
let apples = L10n.applesCount(3)
let bananas = L10n.bananasOwner(5, "Olivier")
Licence
This code and tool is under the MIT Licence. See the LICENCE
file in this repository.
Attributions
This tool is powered by
- Stencil and few other libs by Kyle Fuller
- SwiftGenKit and StencilSwiftKit, our internal frameworks at SwiftGen
It is currently mainly maintained by @AliSoftware and @djbe. But I couldn't thank enough all the other contributors to this tool along the different versions which helped make SwiftGen awesome! 🎉
If you want to contribute, don't hesitate to open a Pull Request, or even join the team!
Other Libraries / Tools
If you want to also get rid of String-based APIs not only for your ressources, but also for UITableViewCell
, UICollectionViewCell
and XIB-based views, you should take a look at my Mixin Reusable.
If you want to generate Swift code from your own Swift code (so meta!), like generate Equatable
conformance to your types and a lot of other similar things, use Sourcery.
SwiftGen and Sourcery are complementary tools. In fact, Sourcery uses Stencil
too, as well as SwiftGen's StencilSwiftKit
so you can use the exact same syntax for your templates for both!
You can also follow me on twitter for news/updates about other projects I am creating, or read my blog.
Github
link |
Stars: 6780 |
Related Packages
You may find interesting
Dependencies
Releases
6.4.0 - 2020-10-07T19:46:13
New Features
- The built-in templates will now correctly handle Swift Package Manager resources, using
Bundle.module
if it's available. As before, you can override the usedBundle
using thebundle
orlookupFunction
template parameters.
Arnaud Dorgans #763 - Added
config generate-xcfilelist
subcommand to generate input and outputxcfilelist
s based on your configuration file. These files should then be used in an Xcode build step that executesswiftgen config run
. Don't forget to regenerate the file lists after adding/removing resources in your project in a way that might impact them.
@CraigSiemens #441 - Colors: the XML parser now accepts a
colorFormat
option, used to change the color format. The default format isrgba
.
@kevinstier #562 #768 - IB: Added support for instantiating scenes while providing a
creator
block, commonly used for dependency injection. This feature is available in generated code starting from iOS 13, tvOS 13 and macOS 10.15.
@matsune David Jennes #778
Bug Fixes
- Plist: Update the parsing strategy (using
Codable
) to fix parsing ofBool
values asInteger
in some cases.
@fortmarek Olivier Halligon #779 - JSON/Plist/YAML: fixed issue with
inline
templates which incorrectly generated1
/0
as values, instead oftrue
/false
as expected.
David Jennes #779 #783 - JSON: the parser now correctly recognizes
0
and1
asInt
(instead ofBool
).
David Jennes #786
Internal Changes
6.3.0 - 2020-08-04T21:59:54
Deprecations
- Fonts: the generated
Font
typealias (toUIFont
/NSFont
) is deprecated and will be removed in the next major release.
David Jennes #728
New Features
- Strings: support for plurals declared in
.stringsdict
files.
Florian Fittschen #184 #634 - Fonts: the templates now support a new
fontTypeName
template parameter that you can use to change the name of thestruct
representing a font to something else.
David Jennes #728 - Fonts: the templates now support a new
fontAliasName
that you can use to change thetypealias
's name fromFont
to something else. For example: this is useful when working with SwiftUI which already defines aFont
type. Note that as thistypealias
is deprecated (see deprecations above), this template parameter will also be removed in the next major release.
David Jennes #647 #728 - CoreData: Deprecates
fetchRequest()
and addsmakeFetchRequest()
to avoid ambiguous function usage.
David Rothera #726 - XCAssets: image assets now load faster on macOS if they're in the
main
bundle. MacOS only provides a caching mechanism for images in themain
bundle, for other cases you may need to provide your own caching mechanism as needed.
David Jennes #648 #733 - Fonts/IB/JSON/Plist/Strings/XCAssets: all templates that load data at runtime from a bundle now support a
bundle
template parameter, which you can use to override the bundle from which resources are loaded. Check out the template specific documentation for more information. For an in-depth explanation, also check the customize loading of resources article.
David Jennes #737 - Fonts/IB/JSON/Plist: Similar to the
strings
templates, these templates now support alookupFunction
template parameter, which allows you to provide your own resource lookup mechanism at runtime. Check the template specific documentation for more information. For an in-depth explanation, also check the customize loading of resources article.
David Jennes #738
Bug Fixes
- Strings: fix incorrect interpretation of format placeholders when there were missing positional parameters (e.g.
"%2$@"
without a%1$…
defined).
@AliSoftware #634
6.2.1 - 2020-07-05T20:53:28
There are no major changes in this release, although JSON & Plist template writers may want to read the small migration guide to prepare for upcoming context changes.
Deprecations
- JSON & Plist: if you wrote your own templates, know that the
documents
property of a file has been deprecated in favour ofdocument
. The olddocuments
property will be removed in the next major release.
David Jennes #702 #732
Bug Fixes
- Prevent generating
default.profraw
(code coverage) files.
David Jennes #722 - JSON/Plist/YAML: Fix issue with homogeneous
Array
s in the Inline templates (such as[String
]).
#687 @fjtrujy - Avoid breaking the system swift installation when installing SwiftGen via Homebrew on macOS 10.14.4 or higher.
David Jennes #686 #730
Internal Changes
- Parsers are now executed in parallel, making SwiftGen faster when multiple parsers are used. Note: only applies when using a configuration file.
Marcelo Fabri #699 - Use
JSONSerialization
instead ofYams
for parsing JSONs, making thejson
parser faster.
Marcelo Fabri #698 - JSON/Plist/YAML: Lazily evaluate
metadata
of documents, making SwiftGen faster if themetadata
field is never used in a template.
Marcelo Fabri #700
6.2.0 - 2020-06-19T01:34:16
⚠️ This minor version contains a lot of deprecations that may apply to your configuration and how you use SwiftGen. With the exception of swift3
templates (which have been removed), everything should still work as before. But be warned that all features marked as deprecated will be removed in SwiftGen 7.0.
Read the SwiftGen 6.2 Migration Guide for a list of changes you'll need to apply.
Breaking Changes
- As Swift 3 is officially no longer maintained, we're obsoleting the Swift 3 templates and they are no longer included with SwiftGen. You can still use the old swift 3 templates by getting them from older SwiftGen versions, or from GitHub by browsing older tags.
David Jennes #601 #691
Deprecations
- XCAssets: the
colorAliasName
andimageAliasName
template parameters are now deprecated and will be removed in the next major release.
David Jennes #614 - The use of
swiftgen <parser>
(e.g.swiftgen strings
,swiftgen xcassets
, …) command line for running individual parsers is now deprecated in favor ofswiftgen run <parser>
. See "New Features" below.
@AliSoftware #705 - The subcommand
swiftgen templates
has been renamedswiftgen template
(singular); the plural form of the command has been deprecated and will be removed in next major version.
@AliSoftware #697 - The ability for SwiftGen to search custom named templates in
~/Library/Application Support
has been deprecated and will be removed in SwiftGen 7.0. This little known feature made SwiftGen dependent on the machine it was running on. UsetemplatePath
to reference custom templates by path instead.
@AliSoftware #717
New Features
- Invoking individual parsers from the command line is now done via
swiftgen run <parser>
. We still highly recommend to use a configuration file for flexibility and performance reasons in your projects, and only useswiftgen run <parser>
for things like quick iterations when writing your own custom templates.
@AliSoftware #705 - You can now easily create a new config file using
swiftgen config init
. This will create an example and commented config file and open it to let you edit it to your needs. Note that the generated config file is static content which doesn't take the user's project into account (though that might change in the future).
@AliSoftware #694 - You can now use
swiftgen template doc [parser] [templateName]
on the command line to quickly open the documentation for templates on GitHub directly from your terminal.
@AliSoftware #697 - Each parser now accepts an
options
dictionary, with which you can set internal parser settings to change its behaviour. See the parser's specific documentation for available options.
David Jennes #587 #597 - Strings: the parser now accepts a
separator
option, used to split keys into structured components. The default separator remains.
. For more information, check the parser's documentation.
David Jennes #576 #588 - Core Data: the built-in templates now support an optional
extraImports
parameter. With this you can provide a list of modules to additionally import, for when you have properties with types from external modules. For more information, check the template's documentation.
David Jennes #591 #592 - Core Data: the built-in templates now support
RawRepresentable
attributes (such asenum
,OptionSet
, …). They'll check the "User Info" of an attribute for aRawType
key, which should be set to the type name you want to use for that attribute. To avoid optional attributes, you can also add theunwrapOptional
user info key. For more information, check the template's documentation.
David Jennes #566 #609 #593 #610 - Strings: the built-in templates now accept a parameter
lookupFunction
for customizing the localization function, check the template documentation for more information.
Steven Magdy 426 468 573 716 - Strings: templates to generate Objective-C. Please check the template's documentation for more information.
Eric Slosser SwiftGen/SwiftGen#378 - XCAssets: the parser now supports AR Resource Groups, together with reference images and objects.
David Jennes #614 - Templates: Bundle now use static property on BundleToken for better performance.
shuoli84 #623 - All parsers now have built-in Swift 5 templates.
David Jennes #595 #600 - Most templates now accept a parameter to force having the file name used as namespace (
enum <FileName>
) in generated code even if there's only one single input file.
Viktoras Laukevičius #669 @AliSoftware #693
Bug Fixes
- SwiftGen now properly shows a better help message and the command usage when running an incomplete command, instead of complaining about a config file.
@AliSoftware #706 - XCAssets: improved the performance for color assets by caching the resolved colors.
David Jennes #578 #589 - Core Data:
entityName
is now correctly aclass var
instead of aclass func
.
David Jennes #590 - Strings: we now correctly generate the type
Any
(instead ofString
) for%@
placeholders.
David Jennes 620 - Colors: Reduce initializer type inference for improved compilation performance.
Markus Faßbender #663 - Config Lint: fix config lint not processing relative paths containing ".." correctly.
Wolfgang Lutz #688 - Core Data: the generated code was missing
,
(comma) for fetch requests with multiple arguments.
David Jennes #692 - Colors: Fix compile time warning when long expression type checking is enabled.
Ryan Mason-Davies #704 #710
Internal Changes
- The main branch of the repository has been renamed from
master
tostable
. If you pointed yourPodfile
or dependency managment tool tomaster
instead of an official release/tag, you will have to update the branch name in your dependency file.
@AliSoftware #714 - Documentation: Improved doc for creating custom templates, and added a Documentation Table of Contents.
@AliSoftware #713 - Refactoring: Reduce globals & rearrange CLI code.
@AliSoftware #586 - Moved generated test output files into subdirectories per template.
David Jennes #598 - Compile generated output using configuration files for easier management.
David Jennes #365 #599 - XCAssets: renamed the catalogs we use for sample code & testing to avoid some confusion.
David Jennes #613 - Update SwiftLint and enable some extra SwiftLint rules.
David Jennes #617 - Some CI fixes related to software versions.
Patrick Nollet #645 - Updated to CocoaPods 1.9.0.
David Jennes #619 - Updated Pods and Gems dependencies.
David Jennes #684
6.1.0 - 2019-01-29T18:46:28
Changes in core dependencies of SwiftGen
New Features
- Adds support for generating code from Core Data models.
Grant Butler David Jennes Igor Palaguta #455 #567 #575 #581 #45 #185 #191 #195 - Config: expand environment variables in YAML files.
Wolfgang Lutz #355 #564 - Each command now accepts a
filter
option, which accepts a regular expression for filtering input paths. The filter is applied to individual paths as well as when the command recurses into directories.
David Jennes #383 #570
Bug Fixes
- Colors: Fix an issue where the
public
access modifier was not being added correctly in theliterals-swift3
andliterals-swift4
templates when thepublicAccess
parameter was specified. Also remove some uneccessarypublic
access modifiers from theswift3
andswift4
templates.
Isaac Halvorson #549
Internal Changes
- Resolve path if the binary is a symbolic link in order to find bundled templates.
Liquidsoul #559 - Update to SwiftLint 0.30.1 and enable some extra SwiftLint rules.
David Jennes #574 #583
6.0.2 - 2018-10-07T22:17:13
Changes in other SwiftGen modules
Bug Fixes
- Strings: rolled back the changes in #503, to ensure
%%
is correctly unescaped.
David Jennes #542 - Strings: generate the correct types for
%c
and%p
.
David Jennes #543 - SPM/Mint: SwiftGen now provides correct version information, instead of "0.0".
David Jennes #544
6.0.1 - 2018-10-04T01:02:32
Changes in other SwiftGen modules
Bug Fixes
- IB: Fix missing
import AppKit
/import UIKit
in some rare cases.
David Jennes #515 #519 - IB: Fix issue with segues-swift4 template when compiled with Swift 4.2 on macOS.
Olivier Halligon #515 #518 - SPM/Mint: Update the Stencil version to 0.13.1.
David Jennes #527 - Ensure the
templates
subcommand properly works with the deprecatedstoryboards
subcommand. David Jennes #529 - Ensure configuration file errors show as red in Xcode.
Olivier Halligon #533 #516 - Strings: Ensure the parser correctly handles keys ending with a
.
and empty key components.
David Jennes #531
Internal Changes
- Integrated Danger to help on contributions by giving automatic feedback.
Olivier Halligon #520 #524
6.0.0 - 2018-09-29T01:06:51
⚠️ This major version is a big milestone in which a lot of refactoring and cleaning has been done. Many features added over previous releases have been reworked and unified, while also preparing SwiftGen for future additions. This means that you'll need to adapt your configuration files (or command line invocations) and custom templates to work with this new major version.
Read the SwiftGen 6.0 Migration Guide for a list of changes you'll need to apply.
Changes in other SwiftGen modules
Breaking Changes
- Don't normalize string keys while parsing, let all transformation be done on template side. This makes the developer responsible to keep the language file organized, duplications won't be removed.
Diego Chohfi #257 - Remove Swift 2 support.
David Jennes #420 - Renamed the
storyboards
command toib
, to better reflect it's purpose. An alias forstoryboards
still exists, but it will be removed at some point.
David Jennes #423 - XCAssets: the generated templates won't namespace groups by default anymore, use the
forceProvidesNamespaces
flag to enable this behaviour again.
jechris #453 - XCAssets: the templates won't generate any all-values accessors anymore by default. Use the
allValues
flag to enable this behaviour again. Note: this replaces the oldnoAllValues
flag (with an inverse behaviour).
David Jennes #480 - XCAssets: Dropped the deprecated
allValues
constant, use the type specific constants such asallColors
,allDataItems
andallImages
. The default value ofimageAlias
has also been changed fromImage
toAssetImageTypeAlias
, to be consistent with the other types.
David Jennes #482 - Interface Builder: split up the storyboards template into 2 parts, one for scenes and one for segues.
David Jennes #419
New Features
- Add ability to list all custom fonts and register them using
FontFamily.registerAllCustomFonts
.
Olivier Halligon #394 - Add support for Swift Package Manager and Mint.
Yonas Kolb #411 - The
swiftgen.yml
config file now accepts multiple outputs for each command, allowing you to generate multiple outputs from the same files and content. This also means that theoutput
parameter is now deprecated, in favour of theoutputs
parameter, and it may be removed in a future version of SwiftGen. Similarly, thepaths
parameter has been renamed toinputs
for consistency. You can always useswiftgen config lint
to validate your configuration file.
David Jennes #424 #510 - Use
swiftlint:disable all
in generated files to avoid interference with SwiftLint rules custom to the host project.
Frederick Pietschmann David Jennes #409 #506 - XCAssets: Added support for
NSDataAssets
.
Oliver Jones #444 - Organised the generated code in sections for better readability, with all generated constants at the top of the file.
David Jennes Olivier Halligon #456 #481 - Added support for JSON, Plist and YAML files using the
swiftgen json
,swiftgen plist
andswiftgen yaml
commands. The parsed contexts and the generated files for each command have been kept quite similar, for easier switching between file formats.
John T McIntosh Toshihiro Suzuki Peter Livesey David Jennes #379 #359 #288 #188 #493 #504 - Updated the playgrounds with the new
json
,plist
andyaml
commands, and updated the other pages to reflect the template changes.
David Jennes #495 - We're deprecating the old
--template
CLI option in favor of--templateName
, to better match the naming of the other options and the configuration file. The old--template
option will remain until the next major version.
David Jennes #509
Bug Fixes
- Fix memory leak in generated code for Fonts.
Olivier Halligon #394 - Interface Builder: ensure the templates handle
GLKViewController
,AVPlayerViewController
andNSPageController
correctly.
David Jennes #404 #414 - Interface Builder: ensure the parser can handle files with and without "trait variations".
David Jennes #367 #429 - Restrict
SceneType
andInitialSceneType
to UIViewController when not targeting AppKit. When targeting AppKit, remove superfluousAny
.
Darron Schall #463 #464 - Fonts: disable a warning in generated font files for projects with
conditional_returns_on_newlines
SwiftLint rule enabled.
Ryan Davies #436 #465 - Interface Builder: the parser and templates now handle the "Inherit module from target" setting.
David Jennes #435 #485 - Strings: the parser now correctly handles formats such as
% d
and%#x
.
David Jennes #502 - Strings: ensure strings without arguments are not processed using
String(format:)
.
David Jennes #503
Internal Changes
- Migrated to CircleCI 2.0.
David Jennes #403 - Switched to using SwiftLint via CocoaPods instead of our own install scripts.
David Jennes #401 - Enabled some extra SwiftLint rules for better code consistency.
David Jennes #402 #476 - Updated to latest Xcode (10.0.0) and Swift 4.2.
David Jennes #415 #498 - Update to Stencil 0.13.0, and use some of it's new filters in our templates.
David Jennes #416 #475 #498 - Store testing contexts as YAML files instead of PLISTs.
David Jennes #418 #461 - Refactor the parsers as they're getting more complex.
David Jennes #417 #422 - Disabled a SwiftLint rule for function parameter count.
Oleg Gorbatchev #428 - Fix missing link in the README.
Takeshi Fujiki #459
5.3.0 - 2018-05-16T19:15:46
Changes in other SwiftGen modules
New Features
- XCAssets: exposed getter for image name string.
Abbey Jackson SwiftGen/templates#85 - XCAssets: exposed getter for color name string.
Stephan Diederich SwiftGen/templates#87 - Allows to set all properties as
public
by using--param publicAccess
on all templates.
Olivier Halligon SwiftGen/templates#84 Txai Wieser SwiftGen/templates#81
Internal Changes
- Merged the
SwiftGenKit
andtemplates
repositories back into this repository for easier development and maintenance.
David Jennes #356
5.2.1 - 2017-10-24T12:47:20
Bug Fixes
- Fix SwiftGen no longer working using CLI parameters (instead of config file).
David Jennes #347 - Errors now properly exit with a non-zero exit code.
Olivier Halligon #348 swiftgen --help
prints the full help back again (and not just the help of the defaultconfig run
subcommand).
Olivier Halligon #349
5.2.0 - 2017-10-22T17:20:05
Changes in other SwiftGen modules
New Features
- You can now use a
swiftgen.yml
file to configure SwiftGen! 🎉
Read more about it in the dedicated documentation.
Olivier Halligon #337 - Storyboards: Added a new
ignoreTargetModule
parameter if you're using storyboards in multiple targets, to avoid issues with the generated code.
Julien Quéré SwiftGen/templates#36
Bug Fixes
- Fixes an issue in High Sierra where the output of the processed Catalog Entries was not ordered alphabetically.
Yusuke Kuroiwa Francisco Diaz SwiftGen/SwiftGenKit#57 - Fonts: fix code which checks if a font is already registered.
Vladimir Burdukov SwiftGen/templates#77 - SwiftLint rules: Disabled the
superfluous_disable_command
rule for allswiftlint:disable
exceptions in all templates.
Olivier Halligon SwiftGen/SwiftGen#334 SwiftGen/templates#83 - When installing SwiftGen via CocoaPods, the unneeded
file.zip
is not kept inPods/SwiftGen/
anymore (freeing ~5MB on each install of SwiftGen made via CocoaPods!).
Olivier Halligon #342
5.1.2 - 2017-09-25T20:38:11
- Allows the SwiftGen source code to be built with Xcode 9.
This also has the nice side-effect of making the homebrew installation of SwiftGen also available for macOS 10.13.
Olivier Halligon David Jennes #330 SwiftGen/Eve#10
5.1.1 - 2017-08-21T17:02:15
Changes in other SwiftGen modules
Bug Fixes
- XCAssets: fixed some compatibility issues with the swift 3 template on Xcode 8, and with other templates.
David Jennes SwiftGen/templates#76
5.1.0 - 2017-08-20T18:54:34
Changes in other SwiftGen modules
New Features
- Added Swift 4 templates. Use
-t swift4
or whatever variant you want to use (seeswiftgen templates list
for the available names).
David Jennes SwiftGen/templates/#67 - XCAssets: Added support for named colors. When using
swiftgen xcassets
the bundled templates will now also include colors found in the Asset Catalog in addition to the images.
David Jennes SwiftGen/templates/#68 - Fonts: the path to fonts will now default to just the font filename, but you can disable
this behaviour by enabling the
preservePath
parameter.
David Jennes SwiftGen/templates/#71 - Colors: new template that uses
#colorLiteral
s.
Useswiftgen colors -t literals-swift3
/swiftgen colors -t literals-swift4
to use them.
David Jennes SwiftGen/templates/#72
5.0.0 - 2017-08-12T17:16:01
⚠️ This major version is a big milestone in which a lot of refactoring and cleaning has been done. Many features added over previous releases have been reworked and unified, while also preparing SwiftGen for future additions. This means that you'll need to adapt your command line invocations and custom templates to work with this new major version.
Read the SwiftGen 5.0 Migration Guide for a list of changes you'll need to apply.
Changes in other SwiftGen modules
Breaking Changes
- Removed deprecated CLI options. Please consult the migration guide should you still use them.
David Jennes #301 - Disable default value for named template option and ensure that there is a template option.
Liquidsoul #283 - Templates are now grouped by subcommand on the filesystem. This is only important if you had custom templates in the
Application Support
directory. To migrate your templates, place them in a subfolder with the name of the subcommand, and remove the prefix of the template filename.
David Jennes #304 - The
images
command has been renamed toxcassets
to better reflect its functionality.
Olivier Halligon #317
Notable breaking changes from other SwiftGen repositories
- Many deprecated templates have been removed (or merged), and others have been renamed to reflect new behaviours. Please check the templates migration guide for more information.
David Jennes SwiftGen/templates#47 - There have been some breaking changes in the generated code for storyboards. Please check the templates migration guide for more information, where we also provide a compatibility template.
Olivier Halligon SwiftGen/templates#65 - Removed deprecated template context variables, and restructured many others. Please check the SwiftGenKit migration guide for more information.
David Jennes SwiftGen/SwiftGenKit#5 - Some filters have been removed in favour of Stencil's built in versions, and other filters have been updated to accept parameters. Please consult the StencilSwiftKit migration guide for more information.
David Jennes SwiftGen/StencilSwiftKit#5 SwiftGen/StencilSwiftKit#6
New Features
- Colors and strings commands now accept multiple input files. With these 2 additions, all swiftgen generator commands are able to handle multiple input files.
David Jennes #313 SwiftGen/SwiftGenKit#40 SwiftGen/SwiftGenKit#41
Internal Changes
- Improved installation instructions in the README.
Olivier Halligon #303
Notable internal changes from other SwiftGen repositories
- Switch back from
actool
to an internal parser to fix numerous issues with the former. This fixes issues a few people encountered when using asset catalogs that contained some of the less common set types.
David Jennes #228 SwiftGen/SwiftGenKit#43
4.2.1 - 2017-05-09T03:51:32
• 🔗 SwiftGenKit 1.1.0 • 🔗 StencilSwiftKit 1.0.2 • 🔗 Stencil 0.9.0 • 🔗 templates 1.1.0
Bug Fixes
- Fix a bug in which the version of SwiftGen was reported as
v0.0
byswiftgen --version
.
Olivier Halligon
Internal Changes
- Update StencilGenKit to 1.0.2 and update Circle CI to Xcode 8.3.
Diogo Tridapalli #295 - Switch from Travis CI to Circle CI, clean up the Rakefile in the process.
David Jennes Olivier Halligon #269 #291 - Fix remaining enum names not Swift 3 compliant.
Liquidsoul #297 - Added the
CONTRIBUTING.md
file to help new contributors.
Olivier Halligon Cihat Gündüz #149 #298
4.2.0 - 2017-02-20T08:16:00
• 🔗 SwiftGenKit 1.0.1 • 🔗 StencilSwiftKit 1.0.0 • 🔗 Stencil 0.8.0 • 🔗 templates 1.0.0
ℹ️ Don't forget to look at the CHANGELOGs of the other repositories too (links above) in addition to this one, to see all the changes across all of SwiftGen.
Bug Fixes
Notable bug fixes from other SwiftGen repositories
- Storyboards templates won't
import
your app module anymore, removing that annoying warning.
@djbe SwiftGen/templates/#19
New Features
- You can now pass custom parameters to your templates using the
--param X=Y
syntax.
@djbe #265- This command-line option can be repeated at will and used to pass structured custom parameters (e.g.
--param tabs=2 --param foo.bar=1 --param foo.baz=2
). - You can then use them in your templates using e.g.
{{param.tabs}}
,{{param.foo.bar}}
&{{param.foo.baz}}
.
- This command-line option can be repeated at will and used to pass structured custom parameters (e.g.
- Templates can now access environment variables via the
env
key of the Stencil context (e.g.{{env.USER}}
,{{env.LANG}}
).
@djbe #265- This is especially useful when integrating SwiftGen as a Script Build Phase in your Xcode project as you can then access Xcode Build Settings exposed as
environment variables by Xcode, e.g.
{{env.PRODUCT_MODULE_NAME}}
.
- This is especially useful when integrating SwiftGen as a Script Build Phase in your Xcode project as you can then access Xcode Build Settings exposed as
environment variables by Xcode, e.g.
Notable new features from other SwiftGen repositories
- Use an explicit bundle parameter to support frameworks for all templates.
@NachoSoto @djbe #255 SwiftGen/templates/#17
Deprecations
In preparation for an upcoming cleanup of SwiftGen to remove some legacy code as well as Stencil old variables, tags and filters, and change the default templates to Swift 3, some things are being deprecated and will be removed in the next major version 5.0.
As a result, if you wrote custom templates, you should already prepare for the upcoming 5.0 by migrating your templates to use the new variables (already avaiable in SwiftGen 4.2 / SwiftGenKit 1.0).
See #244 and the Migration Guide in the Wiki for a list of deprcations and their replacements.
Internal changes
- SwiftGen has migrated to its own GitHub organization 🎉.
- SwiftGen has been split in multiple repositories and separate modules.
@AliSoftware @djbe #240 #265- The present SwiftGen is the CLI parsing. It is in charge of calling the frameworks, feeding them appropriate parameters according to the command line arguments.
- SwiftGenKit is the framework responsible for parsing your assets/resources and turning them into a structured representation compatible with
Stencil
templates. - StencilSwiftKit is a framework adding some extensions to the template engine Stencil used by SwiftGen. It adds some tags and filters as well as convenience methods shared both by SwiftGen itself and by Sourcery.
- The SwiftGen templates has been moved into a dedicated templates repo so they can evolve and be unit-tested separately of SwiftGen.
Note: The next minor version will focus on bringing more documentation for all this new structure and improve ease of future contributions.
4.1.0 - 2017-01-03T19:01:54
Bug Fixes
- Strings: fix issue with
dot-syntax-swift3
where function definitions were not Swift 3 guidelines compliant.
David Jennes #248 - Snake cased keys with uppercase letters are correctly camel cased again. Cihat Gündüz #226
New Features
- Added a
storyboards-osx-swift3
template.
Felix Lisczyk #225 - Added a
strings-no-comments-swift3
template that does not include the default translation of each key.
Loïs Di Qual #222 - Images: new dot-syntax template, use
dot-syntax-swift3
ordot-syntax
(for Swift 2.3).
David Jennes #206 - Reworked the "dot-syntax" and "structured" templates to use the new
macro
andcall
tags, which greatly simplifies the templates, and also removes the limitation of 5-level deep structures.
David Jennes #237 - Storyboards: automatically detect the correct modules that need to be
imported. The
--import
option has therefore been deprecated, as well as theextraImports
template variable. Instead use the the newmodules
variable, which offers the same functionality.
David Jennes #243 - Support multiple input paths for some commands:
David Jennes #213fonts
accepts multiple input directories, all found fonts will be added to thefamilies
template variable.images
now supports multiple asset catalogs as input. Templates can now use thecatalogs
variable to access each individual catalog.storyboards
accepts multiple paths (to folders orstoryboard
files). All found storyboards will be available in thestoryboards
template variable.
Internal changes
- Better error handling in the
colors
command.
David Jennes #227 - Stencil: added two new tags
macro
andcall
, see the documentation. for in depth explanations on how to use them.
David Jennes #237 - SwiftLint: Remove
switch_case_on_newline
warning for generated color file.
Mickael Titeca #239 - Stencil: better string filter testing and fixed a small issue with
lowerFirstWord
.
David Jennes #245
4.0.1 - 2016-12-04T01:02:53
Bug Fixes
- Escape newlines again in .strings file keys.
ChristopherRogers #208 - Fix broken
import
option added in 4.0.0.
David Jennes #214 - Show an error when the provided path to the
images
command is not an asset catalog.
David Jennes #217 - Strings dot-syntax template: use
enum
s for namespacing instead ofstruct
s.
David Jennes #218
Internal changes
- Swift 3 migration.
ahtierney #201 - Restructure the SwiftGen project to build as an
.app
during developement, for easier debugging in Xcode.
ahtierney #204 - Consolidate the use of PathKit internally.
David Jennes #212 - Updated Stencil to 0.7.2.
Kyle Fuller #216
4.0.0 - 2016-11-20T18:23:15
- Add support for multiline string in *.strings file.
Jeong Yonguk #192 - Change swift 3 storyboard segue template's sender from
AnyObject
toAny
.
Derek Ostrander #197 - Fix swift 3 storyboard templates to be compliant with swift 3 api design guidelines.
Afonso #194 - Add option to add import statements at the top of the generated swift file (for
storyboards) using the
import
flag. Multiple imports can be added by repeating this flag.
David Jennes #175 - Remove the
key
param label from thetr
function for Localized String in the swift3 template.
AndrewSB #190 - Escape reserved swift keywords in the structured and dot-syntax generated strings code.
Afonso #198 - The
swiftgen images
command now uses theactool
utility to parse asset catalogs, ensuring that the parser correctly handles namespaced folders.
David Jennes #199
3.0.1 - 2016-11-06T19:11:54
- Add support for Xcode 8 and Swift 2.3.
(Should still compile in Xcode 7.3 but theRakefile
to build, install and release requires Xcode 8).
Valentin Knabel Ignacio Romero Zurbuchen HanxuanZhou Syo Ikeda
3.0.0 - 2016-09-04T17:46:13
- Add template that calls
NSLocalizedString()
separately for each string, which is useful when trying to extract strings in the app to a.strings
file.
Ahmet Karalar - Add some
file_length
and similar SwiftLint exceptions in bundled templates, as files generated by SwiftGen might contain lots of constants and can be long by design.
Olivier Halligon - Error messages ("template not found", etc) are now printed on
stderr
.
Olivier Halligon - Add more
swiftgen templates
subcommands.
Olivier Halligonswiftgen templates list
lists all the available templatesswiftgen templates which <name>
prints the path to the template named<name>
swiftgen templates cat <name>
prints the content to the template named<name>
<name>
here can be either a subcommand name likecolors
or a composed namecolors-rawValue
for a specific template.
- Fix swift 3 renaming change in strings-swift3.stencil.
Kilian Koeltzsch, #150 - Fix non-custom class, non-base view controller handling in storyboards-swift3.stencil.
Syo Ikeda, #152 - Add strongly typed
initialViewController()
overrides for storyboard templates if available.
Syo Ikeda, #153, #163 - Add support for font files containing multiple descriptors.
Chris Ellsworth, #156 - Update deprecated usage of generics for Swift 3 / Xcode 8 beta 6.
Chris Ellsworth, #158 - Fix case when missing positional parameters, which leads to parameters in the enum with
unspecified type (undeterminable from the
Localizable.strings
format analysis) where reported asAny
— which is not aCVarArgType
. Now usingUnsafePointer<()>
arguments instead for such odd edge-cases that should never happen anyway.
Olivier Halligon - Now reports an error when it failed to parse a color in a color input file.
Olivier Halligon, #162 - New Strings template (available via
-t dot-syntax
), allowing string keys containing dots (like foo.bar.baz) to be organized as a hierarchy and accessible via dot syntax. Cihat Gündüz, #159 - Update Swift 3 templates to use lowercase enums.
Olivier Halligon, #166 - New Strings template (available via
-t dot-syntax-swift3
), allowing keys with dots in Swift 3 (see above).
Cihat Gündüz, #168
💡 You can now create your custom templates more easier than ever, by cloning an existing template!
e.g. to clone the default
strings-default.stencil
template:
- use
swiftgen templates cat strings --output strings-custom.stencil
- modify the cloned
strings-custom.stencil
template to your liking- use it with
swiftgen strings … --templatePath strings-custom.stencil …
in your projects!
Important Notes
- Some keys for various templates have changed to provide more flexibility and enable some new features in the templates. As a result, if you created your own custom templates, they might not all be totally compatible with SwiftGen 3.0.0 (hence the new major version). Please read the Custom Templates documentation to find out the new Stencil context keys and update your custom templates accordingly.
If you're using one of the bundled templates, all of them have been updated appropriately.
- Also if you use Swift 3, and thus use the
-t swift3
flag to use the Swift 3 templates, be advised those has been modified to take the latest Swift 3 modifications into account (including naming convensions) so your code might need to be updated according to match the latest Swift 3 recommendations.
2.0.0 - 2016-06-28T23:59:25
- Fix issue with txt files bailing on comments.
Derek Ostrander, #140 - Added support for tvOS and watchOS in images, fonts and color templates.
Tom Baranes, #145 - Added enum-based structured identifiers via
-t structured
option.
Cihat Gündüz, #148 - Added support for OSX in storyboards.
Tom Baranes, #131
Note: The Stencil
context keys (the name of the variables used in templates) for storyboard has changed a bit. Especially, class
has been renamed into customClass
(see #131) to better describe the intent (as this isn't defined if there is no custom class set in the Storyboard), and new keys isBaseViewController
and baseType
has been added.
This means that if you did implement your own custom templates for storyboards (instead of using the bundled ones), you'll have to remplace {{class}}
by {{customClass}}
in those storyboard templates, otherwise they'll probably stop working as expected. That's the main reason why the version has been bumped to a major version 2.0.0.
1.1.2 - 2016-06-09T13:11:50
- Fix issue introduced by 1.1.1 in storyboard templates not returning.
Ben Chatelain #138
1.1.1 - 2016-06-08T21:22:43
- Removed the last force-unwrap from storyboard templates.
Olivier Halligon
1.1.0 - 2016-06-06T11:02:43
- Added step to ensure all templates are Swiftlint'ed
and don't violate any code style rule.
Olivier Halligon, h/t AJ9 in #80 - Added support for OSX in images, fonts and color templates.
Tom Baranes, #125, #126, #127 - Added missing FontConvertible protocol conformance to default fonts template.
Ben Chatelain #129
1.0.0 - 2016-06-01T23:30:26
- Restructured colors & fonts templates to workaround the same LLVM issue as #112 with nested types
inside existing UIKit classes in Release/Optimized builds.
Olivier Halligon - Added support for Fonts using the
swiftgen fonts
command.
Derek Ostrander #102 - Added support for TXT (
colors.txt
) files to have named value.
Derek Ostrander, #118 - Restructured image templates to work around an LLVM issue with nested types.
Ken Grigsby, #112 - Added Swift 3 templates for storyboards and strings.
Andrew Breckenridge, #117
0.8.0 - 2016-03-13T20:05:32
- Introducing alternative way to install SwiftGen: using CocoaPods! See README for more details.
Olivier Halligon, #95 - Added support for JSON (
colors.json
) files as input for theswiftgen colors
subcommand.
Derek Ostrander - Use
String(format:locale:arguments:)
and theNSLocale.currentLocale()
in the "string" templates so that it works with.stringdict
files and pluralization.
Olivier Halligon, #91 - Add support for Android
colors.xml
files as input for theswiftgen colors
subcommand.
Olivier Halligon, #15 - Removed the useless
import Foundation
from the "images" templates.
Olivier Halligon - Added computed property
var color: UIColor
to the color templates.
Olivier Halligon
- 2016-02-19T21:09:25
Enhancements
- Fixed build loop by changing SwiftGen to only write to the output file if the generated code is different from the file contents.
Mathias Nagler, #90
Fixes
- Fixed typos in code and descriptions: instanciate -> instantiate. Please note that the default template used for storyboards
storyboards-default.stencil
had to be modified, so make sure to update your codebase accordingly.
Pan Kolega, #83 - Fixed issue in
Rakefile
when trying to install viarake
in a path containing~
.
Jesse Armand, #88
- 2016-02-19T21:09:16
Enhancements
- Updated stencils and unit tests to pass SwiftLint.
Adam Gask, #79 - Updated
storyboards-default.stencil
to better avoid name confusions.
Olivier Halligon- Now
cases
names are suffixed with…Scene
andstatic func
are prefixed withinstantiate…
to lower the risks of a name conflict with your ViewController classes. - The old template is still available but has been renamed
storyboards-uppercase.stencil
- Now
- Added support for
*.clr
files (files to storeNSColorList
's presented in Color Picker on "Color Palettes" tab)
Ilya Puchka, #81