@aligatr
Constants for free!
enum FontFamily {
enum Avenir: String {
case black = "Avenir-Black"
case blackOblique = "Avenir-BlackOblique"
case oblique = "Avenir-Oblique"
case roman = "Avenir-Roman"
func font(size: CGFloat)
-> UIFont! {
return Font(font: self.rawValue, size: size)
}
}
}
12
Slide 13
Slide 13 text
@aligatr
Constants for free!
enum L10n {
/// Welcome to %@, the #%d iOS conference in %@!
case homeGreetings(String, Int, String)
/// Dismiss changes?
case editAlertTitle
/// Changes have been made to the image « %@ »
case editAlertMessage(String)
/// Save
case editAlertSave
/// Dismiss
case editAlertDismiss
}
13
Slide 14
Slide 14 text
No content
Slide 15
Slide 15 text
@aligatr
enum Assets {
static let apple = UIImage(named: "Apple")
static let banana = UIImage(named: "Banana")
static let orange = UIImage(named: "Orange")
static let somePears = UIImage(named: "Some-Pears")
}
15
enum Assets: String {
case apple = "Apple"
case banana = "Banana"
case orange = "Orange"
case somePears = "Some-Pears"
var image: UIImage {
return UIImage(named: self.rawValue)
}
}
Slide 16
Slide 16 text
@aligatr
Templates!
16
Slide 17
Slide 17 text
@aligatr
A Stencil Template
enum Assets {
{% for image in images %}
static let {{image|swiftIdentifier}}
= UIImage(named: "{{image}}")
{% endfor %}
}
17
Slide 18
Slide 18 text
@aligatr
A Stencil Template
enum Assets: String {
{% for image in images %}
case {{image|swiftIdentifier|lowerFirstWord}} = "{{image}}"
{% endfor %}
var image: UIImage {
return UIImage(asset: self)
}
}
extension UIImage {
convenience init!(asset: Assets) {
self.init(named: asset.rawValue)
}
}
18
Slide 19
Slide 19 text
@aligatr
Profit!
✓ Free auto-completion + discovery (font names, …)
✓ Type-safety (typos, types in format strings, …)
✓ Customizable
✓ Generate anything (documentation, even ObjC )
✓ No more maintenance
19
Slide 20
Slide 20 text
@aligatr
Slide 21
Slide 21 text
@aligatr
What about boilerplate code?
struct ImageInfo: Equatable {
let title: String
let author: String
let date: Date
}
func
== (lhs: ImageInfo, rhs: ImageInfo)
-> Bool {
guard lhs.title
== rhs.title else { return false }
guard lhs.author
== rhs.author else { return false }
guard lhs.date
== rhs.date else { return false }
return true
}
21
Slide 22
Slide 22 text
@aligatr
What about boilerplate code?
struct ImageInfo: Equatable {
let title: String
let author: String
let date: Date
let cameraModel: String
let kind: ImageKind
}
func
== (lhs: ImageInfo, rhs: ImageInfo)
-> Bool {
guard lhs.title
== rhs.title else { return false }
guard lhs.author
== rhs.author else { return false }
guard lhs.date
== rhs.date else { return false }
return true
}
22
@aligatr
There are {{types.all.count}} types in this code, including:
- {{types.enums.count}} enums
- {{types.structs.count}} structs
- {{types.classes.count}} classes
There are 22 types in this code, including:
- 11 enums
- 1 structs
- 6 classes
Introspect your code
Template
Generated Code
26
Slide 27
Slide 27 text
@aligatr
What do we want?
Equatable!
struct ImageInfo {
let title: String
let author: String
let date: Date
}
Your code
27
@aligatr
How do we want it?
Automatically!
{% for type in types.implementing.AutoEquatable %}
extension {{ type.name }}: Equatable {}
func
== (lhs: {{ type.name }}, rhs: {{ type.name }})
-> Bool {
{% for variable in type.storedVariables %}
guard lhs.{{ variable.name }}
== rhs.{{ variable.name }}
else { return false }
{% endfor %}
return true
}
{% endfor %}
Template
29
Slide 30
Slide 30 text
@aligatr
How do we want it?
Automatically!
struct ImageInfo : AutoEquatable {
let title: String
let author: String
let date: Date
}
Your code
$ sourcery/bin/sourcery
+
=
30
Slide 31
Slide 31 text
@aligatr
JSON Parsing
struct Contact {
let id: String
let firstName: String
let lastName: String
}
31
@aligatr
Code Gen to the rescue!
{% for type in
types.implementing.AutoJSONDeserializable %}
extension {{ type.name }}: JSONDeserializable {
init?(json: [String: Any]) {
{% for prop in type.storedVariables %}
// ?
{% endfor %}
}
}
{% endfor %}
33
Slide 34
Slide 34 text
@aligatr
Live Templating
daemon mode to write your templates live:
$ sourcery/bin/sourcery
--watch
34
@aligatr
Going Further
• Building an API Client using Sourcery Annotations
• littlebitesofcocoa.com/295-building-an-api-client-with-sourcery-
key-value-annotations
• Generate JSON Parsing code
• github.com/Liquidsoul/Sourcery-AutoJSONSerializable
• Automatic Type Erasure
• github.com/AliSoftware/SourceryTemplates
42
Slide 43
Slide 43 text
@aligatr
Going Further
• Krzysztof’s talk at CraftConf about Sourcery
• https://www.ustream.tv/recorded/102903026
• My Live Demo of SwiftGen at NSBudapest
• Slides: speakerdeck.com/alisoftware
• Video: http://www.ustream.tv/recorded/103135632
• Improve SwiftGen
• We love contributors! ❤ (Free push access)
43