-
Notifications
You must be signed in to change notification settings - Fork 38
SwiftGen 5.0 Migration: compatibility template
If you have been using the -t swift3
template for your storyboards with SwiftGen 4.x, your call site to use them probably looks something like this:
StoryboardScene.Photos.initialViewController()
StoryboardScene.Photos.instantiateEditVC()
With SwiftGen 5.0, that swift3
template for storyboards has improved to be swiftier and use generics to be even more type-safe. But this also means that your call site will have to change to something like this now:
StoryboardScene.Photos.initialScene.instantiate()
StoryboardScene.Photos.editVC.instantiate()
To help you transition, you can imagine use the compatibility template below — together with SwiftGen 5.0's new swift3
template — to generate some compatibility functions with deprecation warnings. This template re-generates the old functions calling the new API, but marked with the @available(*, deprecated, renamed: …)
annotations, allowing you to use Xcode's Fix-It feature to let Xcode do the heavy lifting and apply the renaming for you.
This template won't be bundled in SwiftGen 5.0 (as it's only a tip to use during migration) and won't be maintained. It's only provided as a courtesy, but isn't unit-tested and won't have long-term support.
To use this, copy this template into some swift3-compat.stencil
file:
// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen
{% if platform and storyboards %}
{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %}
{% set prefix %}{% if isAppKit %}NS{% else %}UI{% endif %}{% endset %}
{% set controller %}{% if isAppKit %}Controller{% else %}ViewController{% endif %}{% endset %}
import Foundation
import {% if isAppKit %}Cocoa{% else %}UIKit{% endif %}
{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %}
import {{module}}
{% endfor %}
{% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %}
{% macro className scene %}{% filter removeNewlines %}
{% if scene.customClass %}
{% if scene.customModule %}{{scene.customModule}}.{% endif %}
{{scene.customClass}}
{% else %}
{{prefix}}{{scene.baseType}}
{% endif %}
{% endfilter %}{% endmacro %}
{% for storyboard in storyboards %}
{% set storyboardName %}{{storyboard.name|swiftIdentifier|escapeReservedKeywords}}{% endset %}
extension {{sceneEnumName}}.{{storyboardName}} {
{% if storyboard.initialScene %}
{% set sceneClass %}{% call className storyboard.initialScene %}{% endset %}
@available(*, deprecated, renamed: "initialScene.instantiate()")
static func initialViewController() -> {{sceneClass}} {
return initialScene.instantiate()
}
{% endif %}
{% for scene in storyboard.scenes %}
{% set sceneID %}{{scene.identifier|swiftIdentifier|snakeToCamelCase|lowerFirstWord|escapeReservedKeywords}}{% endset %}
{% set sceneClass %}{% call className scene %}{% endset %}
@available(*, deprecated, renamed: "{{sceneID}}.instantiate()")
static func instantiate{{sceneID|titlecase}}() -> {{sceneClass}} {
return {{sceneID}}.instantiate()
}
{% endfor %}
}
{% endfor %}
{% elif storyboards %}
// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately
{% else %}
// No storyboard found
{% endif %}
Then:
- in a terminal, just ask SwiftGen to generate the compatibility code using this template (e.g.
swiftgen storyboards -p swift3-compat.stencil -o storyboards-compat.swift ./Source
) - integrate the generated file in your project during the migration (in addition to the file generated by
swiftgen storyboards -t swift3 …
that you probably have in your Build Phase) - 💡 You can then use Xcode's Fix-It feature (and the "Editor" > "Fix All in Scope" menu item) to let Xcode do the renaming for you.
- once the migration of your existing code is done, you can just delete the generated compatibility file and start using the new API.