SlideShare a Scribd company logo
REAL WORLD GENERICS IN
SWIFT
@VADYMMARKOV
ABOUT ME
let me = Developer(
name: "Vadym Markov",
specialisation: "iOS",
company: "Hyper Interaktiv AS",
interests: [
"Technology",
"Open Source",
"Music"
]
)
GENERICS, HUH?
DEFINITION
▸ Generic programming is a way to write functions
and data types without being specific about the
types they use

▸ Generic code enables you to write flexible,
reusable functions and types that can work with
any type, subject to requirements that you define
GENERICS AND SWIFT
▸ Generics are one of the most powerful
features of Swift
▸ Much of the Swift standard library is built
with generic code
▸ You’ve already been using generics, even if
you didn’t realise it
SWIFT STANDARD LIBRARY
// Array
var array = [String]()
// Dictionary
var dictionary = [String: String]()
// Enum
var string1 = Optional<String>.Some("Swift")
var string2 = Optional<String>.None == nil
THE PROBLEM
struct IntQueue {
private var items = [Int]()
mutating func enqueue(item: Int) {
items.append(item)
}
mutating func dequeue() -> Int? {
return items.removeFirst()
}
func peek() -> Int? {
return items.first
}
func isEmpty() -> Bool {
return items.isEmpty
}
}
SOLUTION?
struct AnyQueue {
private var items = [Any]()
mutating func enqueue(item: Any) {
items.append(item)
}
mutating func dequeue() -> Any? {
return items.removeFirst()
}
func peek() -> Any? {
return items.first
}
func isEmpty() -> Bool {
return items.isEmpty
}
}
SO NOW WE ARE ABLE TO PUSH STRINGS TO THE STACK, RIGHT?
YES BUT…
▸ We are losing type safety
▸ We also need to do a lot of casting
SOLUTION!
struct Queue<T> {
private var items = [T]()
mutating func enqueue(item: T) {
items.append(item)
}
mutating func dequeue() -> T? {
return items.removeFirst()
}
func peek() -> T? {
return items.first
}
func isEmpty() -> Bool {
return items.isEmpty
}
}
SOLUTION!
var stringQueue = Queue<String>()
stringQueue.enqueue("String")
stringQueue.dequeue() // "String"
var intQueue = Queue<Int>()
intQueue.enqueue(1)
intQueue.dequeue() // 1
WELCOME TO REALITY
GENERIC TYPES
class DataSource<Model, Cell: UITableViewCell> : NSObject,
UITableViewDataSource, UITableViewDelegate {
let cellIdentifier: String
let configureCell: (Model, Cell) -> Void
var cellHeight: CGFloat = 64
var items = [Model]()
var action: (Model -> Void)?
init(cellIdentifier: String,
configureCell: (Model, Cell) -> Void) {
self.cellIdentifier = cellIdentifier
self.configureCell = configureCell
}
// ...
// MARK: - UITableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(
cellIdentifier,
forIndexPath: indexPath)
let item = items[indexPath.item]
if let cell = cell as? Cell {
configureCell(item, cell)
}
return cell
}
// MARK: - UITableViewDelegate
func tableView(tableView: UITableView,
heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return cellHeight
}
func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
guard let action = action else { return }
let item = items[indexPath.row]
action(item)
}
class TeamController: UITableViewController {
static let reusableIdentifier = "TeamCellIdentifier"
var developers = [Developer]()
lazy var dataSource: DataSource<Developer, TableViewCell> = {
[unowned self] in
let dataSource = DataSource(
cellIdentifier: TeamController.reusableIdentifier,
configureCell: self.configureCell)
dataSource.action = self.selectCell
return dataSource
}()
// ...
func configureCell(developer: Developer, cell: TableViewCell) {
cell.textLabel?.text = developer.name
cell.imageView?.image = UIImage(named: "placeholder"))
}
func selectCell(developer: Developer) {
UIApplication.sharedApplication().openURL(developer.githubURL)
}
}
protocol CacheAware {
func object<T: Cachable>(key: String,
completion: (object: T?) -> Void)
}
class DiskStorage: CacheAware {
func object<T: Cachable>(key: String,
completion: (object: T?) -> Void) {
// ...
}
}
// String must conform Cachable
let storage = DiskStorage(name: "Unknown")
storage.add("string", object: "My string”)
storage.object("string") { (object: String?) in }
GENERIC FUNCTIONS
struct ViewModel: Mappable {
// ...
var meta = [String : AnyObject]()
func meta<T>(key: String, _ defaultValue: T) -> T {
return meta[key] as? T ?? defaultValue
}
}
let modelFoo = ViewModel(title: "foo", meta: ["id" : 1])
modelFoo.meta("id", 0) // 1
modelFoo.meta("foo", "bar") // bar
GENERIC FUNCTIONS
WHAT ABOUT PROTOCOLS?
▸Protocols in Swift cannot be defined
generically using type parameters.

▸Instead, protocols can define what are
known as associated types.
ASSOCIATED TYPES
protocol Cachable {
typealias CacheType
static func decode(data: NSData) -> CacheType?
func encode() -> NSData?
}
extension String: Cachable {
typealias CacheType = String
static func decode(data: NSData) -> CacheType? {
// ...
}
func encode() -> NSData? { // ... }
}
ASSOCIATED TYPES
let list: [Cachable] = []
▸ Cachable represents a set of types rather than a
single type
▸ In an array of Cachable, you are not be able to say
anything about the return type of the decode()
method
HOW COULD IT LOOK LIKE?
let list : [Cachable<String>] = []
let’s imagine Swift supporting generic
parameterised protocols
MORE EXAMPLES: OPERATORS
infix operator ?= { associativity right precedence 90 }
public func ?=<T>(inout left: T, right: T?) {
guard let value = right else { return }
left = value
}
public func ?=<T>(inout left: T?, right: T?) {
guard let value = right else { return }
left = value
}
// ...
func testIfLetAssignment() {
let hyper = NSURL(string: "hyper.no")!
let faultyURL = NSURL(string: "/http")
var testURL: NSURL?
testURL ?= hyper // "hyper.no"
testURL ?= faultyURL // "hyper.no"
}
MORE EXAMPLES: PROTOCOL EXTENSIONS
protocol Queueable {
func process() -> Bool
}
extension Array where Element : Queueable {
mutating func processQueue(from: Int, to: Int,
process: ((element: Element) -> Void)) {
// ...
}
}
var testQueue = [Object(), Object()]
testQueue.processQueue()
MORE EXAMPLES: ENUMS
enum Result<T, ErrorType> {
case Success(T)
case Failure(ErrorType)
}
struct UFO {
enum Error: ErrorType {
case NotFound
}
}
func recognizeUFO(completion: Result<UFO, UFO.Error> -> Void) {
var ufo: UFO?
// Some async complex calculations
if let result = ufo {
completion(Result.Success(result))
} else {
completion(Result.Failure(UFO.Error.NotFound))
}
}
WHY GENERICS?
▸ Type safety
▸ Less code duplication
▸ No type casting hell
▸ Public API flexibility
▸ Abstraction is fun
RESOURCES
▸ https://developer.apple.com/swift/
▸ https://github.com/hyperoslo/Orchestra
▸ https://github.com/hyperoslo/Cache
▸ https://github.com/hyperoslo/Spots
▸ https://github.com/hyperoslo/Sugar
QUESTIONS?
HTTPS://GITHUB.COM/VADYMMARKOV
@VADYMMARKOV

More Related Content

PDF
Adopting Swift Generics
PDF
Advanced Swift Generics
PDF
The Ring programming language version 1.3 book - Part 83 of 88
PDF
LetSwift RxSwift 시작하기
PPT
Collection Core Concept
PPTX
Oct13' ----
PPT
Collection v3
PDF
Hadoop + Clojure
Adopting Swift Generics
Advanced Swift Generics
The Ring programming language version 1.3 book - Part 83 of 88
LetSwift RxSwift 시작하기
Collection Core Concept
Oct13' ----
Collection v3
Hadoop + Clojure

What's hot (20)

PDF
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
PPTX
Functional Reactive Programming (FRP): Working with RxJS
PDF
JavaScript ES6
PPTX
03 standard class library
PDF
Functional Core, Reactive Shell
PPTX
ES6 in Real Life
PDF
Swift rocks! #1
PDF
Swift Rocks #2: Going functional
PPT
Java 8 Streams
PDF
jq: JSON - Like a Boss
PDF
The Ring programming language version 1.2 book - Part 5 of 84
PDF
Writing a compiler in go
PDF
Reactive programming with RxSwift
PDF
Pune Clojure Course Outline
PPTX
Introduction to java 8 stream api
PDF
_Function Builders in Swift #love_swift
PPTX
Introduction to Ecmascript - ES6
TXT
123
PDF
A evolução da persistência de dados (com sqlite) no android
PDF
Introduction aux Macros
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
Functional Reactive Programming (FRP): Working with RxJS
JavaScript ES6
03 standard class library
Functional Core, Reactive Shell
ES6 in Real Life
Swift rocks! #1
Swift Rocks #2: Going functional
Java 8 Streams
jq: JSON - Like a Boss
The Ring programming language version 1.2 book - Part 5 of 84
Writing a compiler in go
Reactive programming with RxSwift
Pune Clojure Course Outline
Introduction to java 8 stream api
_Function Builders in Swift #love_swift
Introduction to Ecmascript - ES6
123
A evolução da persistência de dados (com sqlite) no android
Introduction aux Macros
Ad

Similar to Real World Generics In Swift (20)

PDF
Introduction to Swift 2
PDF
Deep Dive Into Swift
PDF
An introduction to functional programming with Swift
PDF
Swift Programming
PDF
Swift Introduction
PDF
Cocoa Design Patterns in Swift
PDF
Introduction to Swift programming language.
PDF
From android/java to swift (3)
PDF
Infinum iOS Talks #1 - Swift done right by Ivan Dikic
PDF
Introduction to Swift
PDF
Quick swift tour
PDF
Cocoaheads Meetup / Alex Zimin / Swift magic
PDF
Александр Зимин (Alexander Zimin) — Магия Swift
PDF
Protocols
PDF
A swift introduction to Swift
PDF
Pooya Khaloo Presentation on IWMC 2015
PDF
From android/ java to swift (2)
PDF
Swift, swiftly
PDF
스위프트를 여행하는 히치하이커를 위한 스타일 안내
PDF
Swift와 Objective-C를 함께 쓰는 방법
Introduction to Swift 2
Deep Dive Into Swift
An introduction to functional programming with Swift
Swift Programming
Swift Introduction
Cocoa Design Patterns in Swift
Introduction to Swift programming language.
From android/java to swift (3)
Infinum iOS Talks #1 - Swift done right by Ivan Dikic
Introduction to Swift
Quick swift tour
Cocoaheads Meetup / Alex Zimin / Swift magic
Александр Зимин (Alexander Zimin) — Магия Swift
Protocols
A swift introduction to Swift
Pooya Khaloo Presentation on IWMC 2015
From android/ java to swift (2)
Swift, swiftly
스위프트를 여행하는 히치하이커를 위한 스타일 안내
Swift와 Objective-C를 함께 쓰는 방법
Ad

Recently uploaded (20)

PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
Cloud computing and distributed systems.
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Encapsulation_ Review paper, used for researhc scholars
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Approach and Philosophy of On baking technology
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPT
Teaching material agriculture food technology
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
The Rise and Fall of 3GPP – Time for a Sabbatical?
Mobile App Security Testing_ A Comprehensive Guide.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Dropbox Q2 2025 Financial Results & Investor Presentation
Digital-Transformation-Roadmap-for-Companies.pptx
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Per capita expenditure prediction using model stacking based on satellite ima...
Reach Out and Touch Someone: Haptics and Empathic Computing
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Chapter 3 Spatial Domain Image Processing.pdf
Cloud computing and distributed systems.
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Encapsulation_ Review paper, used for researhc scholars
The AUB Centre for AI in Media Proposal.docx
Approach and Philosophy of On baking technology
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Teaching material agriculture food technology
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Spectral efficient network and resource selection model in 5G networks

Real World Generics In Swift

  • 1. REAL WORLD GENERICS IN SWIFT @VADYMMARKOV
  • 2. ABOUT ME let me = Developer( name: "Vadym Markov", specialisation: "iOS", company: "Hyper Interaktiv AS", interests: [ "Technology", "Open Source", "Music" ] )
  • 4. DEFINITION ▸ Generic programming is a way to write functions and data types without being specific about the types they use
 ▸ Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define
  • 5. GENERICS AND SWIFT ▸ Generics are one of the most powerful features of Swift ▸ Much of the Swift standard library is built with generic code ▸ You’ve already been using generics, even if you didn’t realise it
  • 6. SWIFT STANDARD LIBRARY // Array var array = [String]() // Dictionary var dictionary = [String: String]() // Enum var string1 = Optional<String>.Some("Swift") var string2 = Optional<String>.None == nil
  • 7. THE PROBLEM struct IntQueue { private var items = [Int]() mutating func enqueue(item: Int) { items.append(item) } mutating func dequeue() -> Int? { return items.removeFirst() } func peek() -> Int? { return items.first } func isEmpty() -> Bool { return items.isEmpty } }
  • 8. SOLUTION? struct AnyQueue { private var items = [Any]() mutating func enqueue(item: Any) { items.append(item) } mutating func dequeue() -> Any? { return items.removeFirst() } func peek() -> Any? { return items.first } func isEmpty() -> Bool { return items.isEmpty } }
  • 9. SO NOW WE ARE ABLE TO PUSH STRINGS TO THE STACK, RIGHT? YES BUT… ▸ We are losing type safety ▸ We also need to do a lot of casting
  • 10. SOLUTION! struct Queue<T> { private var items = [T]() mutating func enqueue(item: T) { items.append(item) } mutating func dequeue() -> T? { return items.removeFirst() } func peek() -> T? { return items.first } func isEmpty() -> Bool { return items.isEmpty } }
  • 11. SOLUTION! var stringQueue = Queue<String>() stringQueue.enqueue("String") stringQueue.dequeue() // "String" var intQueue = Queue<Int>() intQueue.enqueue(1) intQueue.dequeue() // 1
  • 13. GENERIC TYPES class DataSource<Model, Cell: UITableViewCell> : NSObject, UITableViewDataSource, UITableViewDelegate { let cellIdentifier: String let configureCell: (Model, Cell) -> Void var cellHeight: CGFloat = 64 var items = [Model]() var action: (Model -> Void)? init(cellIdentifier: String, configureCell: (Model, Cell) -> Void) { self.cellIdentifier = cellIdentifier self.configureCell = configureCell } // ...
  • 14. // MARK: - UITableViewDataSource func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier( cellIdentifier, forIndexPath: indexPath) let item = items[indexPath.item] if let cell = cell as? Cell { configureCell(item, cell) } return cell }
  • 15. // MARK: - UITableViewDelegate func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return cellHeight } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) guard let action = action else { return } let item = items[indexPath.row] action(item) }
  • 16. class TeamController: UITableViewController { static let reusableIdentifier = "TeamCellIdentifier" var developers = [Developer]() lazy var dataSource: DataSource<Developer, TableViewCell> = { [unowned self] in let dataSource = DataSource( cellIdentifier: TeamController.reusableIdentifier, configureCell: self.configureCell) dataSource.action = self.selectCell return dataSource }() // ... func configureCell(developer: Developer, cell: TableViewCell) { cell.textLabel?.text = developer.name cell.imageView?.image = UIImage(named: "placeholder")) } func selectCell(developer: Developer) { UIApplication.sharedApplication().openURL(developer.githubURL) } }
  • 17. protocol CacheAware { func object<T: Cachable>(key: String, completion: (object: T?) -> Void) } class DiskStorage: CacheAware { func object<T: Cachable>(key: String, completion: (object: T?) -> Void) { // ... } } // String must conform Cachable let storage = DiskStorage(name: "Unknown") storage.add("string", object: "My string”) storage.object("string") { (object: String?) in } GENERIC FUNCTIONS
  • 18. struct ViewModel: Mappable { // ... var meta = [String : AnyObject]() func meta<T>(key: String, _ defaultValue: T) -> T { return meta[key] as? T ?? defaultValue } } let modelFoo = ViewModel(title: "foo", meta: ["id" : 1]) modelFoo.meta("id", 0) // 1 modelFoo.meta("foo", "bar") // bar GENERIC FUNCTIONS
  • 19. WHAT ABOUT PROTOCOLS? ▸Protocols in Swift cannot be defined generically using type parameters.
 ▸Instead, protocols can define what are known as associated types.
  • 20. ASSOCIATED TYPES protocol Cachable { typealias CacheType static func decode(data: NSData) -> CacheType? func encode() -> NSData? } extension String: Cachable { typealias CacheType = String static func decode(data: NSData) -> CacheType? { // ... } func encode() -> NSData? { // ... } }
  • 21. ASSOCIATED TYPES let list: [Cachable] = [] ▸ Cachable represents a set of types rather than a single type ▸ In an array of Cachable, you are not be able to say anything about the return type of the decode() method
  • 22. HOW COULD IT LOOK LIKE? let list : [Cachable<String>] = [] let’s imagine Swift supporting generic parameterised protocols
  • 23. MORE EXAMPLES: OPERATORS infix operator ?= { associativity right precedence 90 } public func ?=<T>(inout left: T, right: T?) { guard let value = right else { return } left = value } public func ?=<T>(inout left: T?, right: T?) { guard let value = right else { return } left = value } // ... func testIfLetAssignment() { let hyper = NSURL(string: "hyper.no")! let faultyURL = NSURL(string: "/http") var testURL: NSURL? testURL ?= hyper // "hyper.no" testURL ?= faultyURL // "hyper.no" }
  • 24. MORE EXAMPLES: PROTOCOL EXTENSIONS protocol Queueable { func process() -> Bool } extension Array where Element : Queueable { mutating func processQueue(from: Int, to: Int, process: ((element: Element) -> Void)) { // ... } } var testQueue = [Object(), Object()] testQueue.processQueue()
  • 25. MORE EXAMPLES: ENUMS enum Result<T, ErrorType> { case Success(T) case Failure(ErrorType) } struct UFO { enum Error: ErrorType { case NotFound } } func recognizeUFO(completion: Result<UFO, UFO.Error> -> Void) { var ufo: UFO? // Some async complex calculations if let result = ufo { completion(Result.Success(result)) } else { completion(Result.Failure(UFO.Error.NotFound)) } }
  • 26. WHY GENERICS? ▸ Type safety ▸ Less code duplication ▸ No type casting hell ▸ Public API flexibility ▸ Abstraction is fun
  • 27. RESOURCES ▸ https://developer.apple.com/swift/ ▸ https://github.com/hyperoslo/Orchestra ▸ https://github.com/hyperoslo/Cache ▸ https://github.com/hyperoslo/Spots ▸ https://github.com/hyperoslo/Sugar