Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Natasha Murashev: Practical Protocol-Oriented P...
Search
Realm
May 10, 2016
Programming
57k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Natasha Murashev: Practical Protocol-Oriented Programming
Realm
May 10, 2016
More Decks by Realm
See All by Realm
WWDC 2017 Review
realm
0
2.2k
Xcode shortcuts
realm
0
4.8k
Self Branding with GitHub
realm
0
4.4k
Realm Mobile Platform overview and demo
realm
0
2.1k
Realm advanced topics and demo
realm
0
2k
Realm introduction Seoul meetup 10
realm
0
2.2k
Stuart Hall: How I got 2.3 Million App Downloads
realm
0
2k
James Majors: What the Swiftly Func?
realm
1
4.3k
Simina Pasat: Continuous everything for iOS apps
realm
0
670
Other Decks in Programming
See All in Programming
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
470
Intent as Code
shoppingjaws
6
1k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
220
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
150
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
260
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
120
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
180
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
4.8k
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
620
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
280
スマート反転とウェブアクセシビリティ
camiha
0
210
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
200
Featured
See All Featured
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
940
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
530
It's Worth the Effort
3n
188
29k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
730
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.6k
How GitHub (no longer) Works
holman
316
150k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
Why Our Code Smells
bkeepers
PRO
340
58k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
890
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Transcript
@NatashaTheRobot
Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind
–- Professor of Blowing-Your-Mind "Swift Is a Protocol-Oriented Programming Language"
None
Practical POP • View • (UITable)ViewController • Networking
POP Views
None
None
// FoodImageView.swift import UIKit class FoodImageView: UIImageView { func shake()
{ let animation = CABasicAnimation(keyPath: "position") animation.duration = 0.05 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 4.0, self.center.y)) animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 4.0, self.center.y)) layer.addAnimation(animation, forKey: "position") } }
// ViewController.swift import UIKit class ViewController: UIViewController { @IBOutlet weak
var foodImageView: FoodImageView! @IBAction func onShakeButtonTap(sender: AnyObject) { foodImageView.shake() } }
None
None
// ShakeableButton.swift import UIKit class ActionButton: UIButton { func shake()
{ let animation = CABasicAnimation(keyPath: "position") animation.duration = 0.05 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 4.0, self.center.y)) animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 4.0, self.center.y)) layer.addAnimation(animation, forKey: "position") } }
// ViewController.swift class ViewController: UIViewController { @IBOutlet weak var foodImageView:
FoodImageView! @IBOutlet weak var actionButton: ActionButton! @IBAction func onShakeButtonTap(sender: AnyObject) { foodImageView.shake() actionButton.shake() } }
None
// UIViewExtension.swift import UIKit extension UIView { func shake() {
let animation = CABasicAnimation(keyPath: "position") animation.duration = 0.05 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 4.0, self.center.y)) animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 4.0, self.center.y)) layer.addAnimation(animation, forKey: "position") } }
class FoodImageView: UIImageView { // other customization here } class
ActionButton: UIButton { // other customization here } class ViewController: UIViewController { @IBOutlet weak var foodImageView: FoodImageView! @IBOutlet weak var actionButton: ActionButton! @IBAction func onShakeButtonTap(sender: AnyObject) { foodImageView.shake() actionButton.shake() } }
None
// Shakeable.swift import UIKit protocol Shakeable { } extension Shakeable
where Self: UIView { func shake() { // implementation code } }
class FoodImageView: UIImageView, Shakeable { } class ActionButton: UIButton, Shakeable
{ }
class FoodImageView: UIImageView, Shakeable, Dimmable { }
class FoodImageView: UIImageView, Dimmable { }
Transparent View Controllers and Dim Backgrounds totem.training
None
POP (UITable)ViewControllers
None
// FoodLaLaViewController override func viewDidLoad() { super.viewDidLoad() let foodCellNib =
UINib(nibName: "FoodTableViewCell", bundle: nil) tableView.registerNib(foodCellNib, forCellReuseIdentifier: "FoodTableViewCell") }
let foodCellNib = UINib(nibName: String(FoodTableViewCell), bundle: nil) tableView.registerNib(foodCellNib, forCellReuseIdentifier: String(FoodTableViewCell))
protocol ReusableView: class {} extension ReusableView where Self: UIView {
static var reuseIdentifier: String { return String(self) } }
extension UITableViewCell: ReusableView { } FoodTableViewCell.reuseIdentifier // FoodTableViewCell
let foodCellNib = UINib(nibName: "FoodTableViewCell", bundle: nil) tableView.registerNib(foodCellNib, forCellReuseIdentifier: FoodTableViewCell.reuseIdentifier)
protocol NibLoadableView: class { } extension NibLoadableView where Self: UIView
{ static var nibName: String { return String(self) } }
extension FoodTableViewCell: NibLoadableView { } FoodTableViewCell.nibName // "FoodTableViewCell"
let foodCellNib = UINib(nibName: FoodTableViewCell.nibName, bundle: nil) tableView.registerNib(foodCellNib, forCellReuseIdentifier: FoodTableViewCell.reuseIdentifier)
extension UITableView { func register<T: UITableViewCell where T: ReusableView, T:
NibLoadableView>(_: T.Type) { let nib = UINib(nibName: T.nibName, bundle: nil) registerNib(nib, forCellReuseIdentifier: T.reuseIdentifier) } }
let foodCellNib = UINib(nibName: "FoodTableViewCell", bundle: nil) tableView.registerNib(foodCellNib, forCellReuseIdentifier: "FoodTableViewCell")
tableView.register(FoodTableViewCell)
extension UITableView { func dequeueReusableCell<T: UITableViewCell where T: ReusableView>(forIndexPath indexPath:
NSIndexPath) -> T { guard let cell = dequeueReusableCellWithIdentifier(T.reuseIdentifier, forIndexPath: indexPath) as? T else { fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)") } return cell } }
guard let cell = tableView.dequeueReusableCellWithIdentifier(“FoodTableViewCell", forIndexPath: indexPath) as? FoodTableViewCell else
{ fatalError("Could not dequeue cell with identifier: FoodTableViewCell") }
let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as FoodTableViewCell
if indexPath.row == 0 { return tableView.dequeueReusableCell(forIndexPath: indexPath) as DesertTableViewCell
} return tableView.dequeueReusableCell(forIndexPath: indexPath) as FoodTableViewCell
iOS Cell Registration & Reusing with Swift Protocol Extensions and
Generics medium.com/@gonzalezreal
Protocol-Oriented Segue Identifiers in Swift natashatherobot.com
None
POP Networking
struct FoodService { func get(completionHandler: Result<[Food]> -> Void) { //
make asynchronous API call // and return appropriate result } }
enum Result<T> { case Success(T) case Failure(ErrorType) }
struct FoodService { func get(completionHandler: Result<[Food]> -> Void) { //
make asynchronous API call // and return appropriate result } }
// FoodLaLaViewController var dataSource = [Food]() { didSet { tableView.reloadData()
} } override func viewDidLoad() { super.viewDidLoad() getFood() } private func getFood() { FoodService().getFood() { [weak self] result in switch result { case .Success(let food): self?.dataSource = food case .Failure(let error): self?.showError(error) } } }
View Controller Tests?!!!
// FoodLaLaViewController var dataSource = [Food]() { didSet { tableView.reloadData()
} } override func viewDidLoad() { super.viewDidLoad() getFood() } private func getFood() { FoodService().getFood() { [weak self] result in switch result { case .Success(let food): self?.dataSource = food case .Failure(let error): self?.showError(error) } } }
// FoodLaLaViewController func getFood(fromService service: FoodService) { service.getFood() { [weak
self] result in // handle result } }
// FoodLaLaViewControllerTests func testFetchFood() { viewController.getFood(fromService: FoodService()) // now what?
}
struct FoodService { func get(completionHandler: Result<[Food]> -> Void) { //
make asynchronous API call // and return appropriate result } }
protocol Gettable { associatedtype T func get(completionHandler: Result<T> -> Void)
}
struct FoodService: Gettable { func get(completionHandler: Result<[Food]> -> Void) {
// make asynchronous API call // and return appropriate result } }
// FoodLaLaViewController override func viewDidLoad() { super.viewDidLoad() getFood(fromService: FoodService()) }
func getFood<S: Gettable where S.T == [Food]>(fromService service: S) { service.get() { [weak self] result in switch result { case .Success(let food): self?.dataSource = food case .Failure(let error): self?.showError(error) } } }
// FoodLaLaViewControllerTests class Fake_FoodService: Gettable { var getWasCalled = false
func get(completionHandler: Result<[Food]> -> Void) { getWasCalled = true completionHandler(Result.Success(food)) } }
// FoodLaLaViewControllerTests func testFetchFood() { let fakeFoodService = Fake_FoodService() viewController.getFood(fromService:
fakeFoodService) XCTAssertTrue(fakeFoodService.getWasCalled) XCTAssertEqual(viewController.dataSource.count, food.count) XCTAssertEqual(viewController.dataSource, food) }
Update: View Controller Data Injection with Storyboards and Segues in
Swift natashatherobot.com
Protocols with Associated Types Alexis Gallagher 2015.funswiftconf.com
None
Practical POP • View • (UITable)ViewController • Networking
Beyond Crusty: Real-World Protocols Rob Napier thedotpost.com
Blending Cultures: The Best of Functional, Protocol-Oriented, and Object-Oriented Programming
Daniel Steinberg realm.io
@NatashaTheRobot