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
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
440
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
610
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
650
XHTMLが残したもの
yosuke_furukawa
PRO
2
700
Laravelのアプリケーションをどこにデプロイするか #ツナギメオフライン.9
akase244
0
120
Webの地図
yosuke_furukawa
PRO
6
4.2k
Security issues being discussed on Web Platforms
petamoriken
0
760
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
160
Kiroで創り、AgentCoreで繋ぐ!AWSで実践する「AI-DLC」から「AIエージェント統合」までの最新地図
licux
4
650
RSSとCodexを使ってX投稿自動化してみた
ochtum
0
110
How I Stole PSI from Android Studio - DroidKaigi2026
worker8
0
110
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
3.9k
Featured
See All Featured
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.7k
The agentic SEO stack - context over prompts
schlessera
0
920
A Tale of Four Properties
chriscoyier
163
24k
Typedesign – Prime Four
hannesfritz
42
3.2k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
930
Music & Morning Musume
bryan
47
7.4k
GitHub's CSS Performance
jonrohan
1033
470k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Code Reviewing Like a Champion
maltzj
528
40k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
57k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
270
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