Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Swift Delhi: Practical POP

1,997 views

Published on

Presented at the Swift Delhi Meetup https://swiftindia.github.io/swiftindia/

Published in: Technology
  • I just began eight weeks past and i have become four check for an entire of $4,15000...this is the best call I made in quite a while! "Much obliged to you for giving American express this unprecedented opportunity to make more cash from home. This further cash has adjusted my life in such a lot of courses in which, bestow you!".......GOOD LUCK Click this snap this connection -=-=-=-=-=-=-=-=-=-=-= http://www.cash-review.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Swift Delhi: Practical POP

  1. 1. @NatashaTheRobot
  2. 2. β€’ @NatashaTheRobot πŸ€– β€’ NatashaTheRobot.com β€’ This Week in Swift Newsletter β€’ Swift Jobs β€’ tryswift.co πŸ₯#πŸŽ‰ β€’ @NatashaTheNomad %
  3. 3. UITableViewDelegate UITableViewDataSource UITextFieldDelegate NSURLSessionDelegate CLLocationManagerDelegate MCSessionDelegate
  4. 4. Protocol-Oriented Programming in Swift Dave Abrahams Professor of Blowing-Your-Mind
  5. 5. –- Professor of Blowing-Your-Mind "Swift Is a Protocol-Oriented Programming Language"
  6. 6. Practical POP β€’ View β€’ (UITable)ViewController β€’ Networking
  7. 7. POP Views
  8. 8. // 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: CGPoint(x: self.center.x - 4.0, y: self.center.y)) animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 4.0, y: self.center.y)) layer.add(animation, forKey: "position") }
  9. 9. // ViewController.swift import UIKit class ViewController: UIViewController { @IBOutlet weak var foodImageView: FoodImageView! @IBAction func onShakeButtonTap(sender: AnyObject) { foodImageView.shake() } }
  10. 10. πŸ’ƒπŸ’ƒπŸ’ƒ
  11. 11. // 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: CGPoint(x: self.center.x - 4.0, y: self.center.y)) animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 4.0, y: self.center.y)) layer.add(animation, forKey: "position") } }
  12. 12. // ViewController.swift class ViewController: UIViewController { @IBOutlet weak var foodImageView: FoodImageView! @IBOutlet weak var actionButton: ActionButton! @IBAction func onShakeButtonTap(sender: AnyObject) { foodImageView.shake() actionButton.shake() } }
  13. 13. πŸ€”
  14. 14. // 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: CGPoint(x: self.center.x - 4.0, y: self.center.y)) animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 4.0, y: self.center.y)) layer.add(animation, forKey: "position") } }
  15. 15. 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() } }
  16. 16. // Shakeable.swift import UIKit protocol Shakeable { } extension Shakeable where Self: UIView { func shake() { // implementation code } }
  17. 17. class FoodImageView: UIImageView, Shakeable { } class ActionButton: UIButton, Shakeable { }
  18. 18. class FoodImageView: UIImageView, Shakeable, Dimmable { }
  19. 19. class FoodImageView: UIImageView, Dimmable { }
  20. 20. Transparent View Controllers and Dim Backgrounds totem.training
  21. 21. πŸ‘―πŸ‘―πŸ‘―πŸ‘―πŸ‘―
  22. 22. POP (UITable)ViewControllers
  23. 23. // FoodLaLaViewController override func viewDidLoad() { super.viewDidLoad() let foodCellNib = UINib(nibName: "FoodTableViewCell", bundle: nil) tableView.register(foodCellNib, forCellReuseIdentifier: "FoodTableViewCell") }
  24. 24. let foodCellNib = UINib(nibName: String(describing: FoodTableViewCell.self), bundle: nil) tableView.register(foodCellNib, forCellReuseIdentifier: String(describing: FoodTableViewCell.self))
  25. 25. protocol ReusableView: class {} extension ReusableView where Self: UIView { static var reuseIdentifier: String { return String(describing: self) } }
  26. 26. extension UITableViewCell: ReusableView { } FoodTableViewCell.reuseIdentifier // FoodTableViewCell
  27. 27. let foodCellNib = UINib(nibName: "FoodTableViewCell", bundle: nil) tableView.register(foodCellNib, forCellReuseIdentifier: FoodTableViewCell.reuseIdentifier)
  28. 28. protocol NibLoadableView: class { } extension NibLoadableView where Self: UIView { static var nibName: String { return String(describing: self) } }
  29. 29. extension FoodTableViewCell: NibLoadableView { } FoodTableViewCell.nibName // "FoodTableViewCell"
  30. 30. let foodCellNib = UINib(nibName: FoodTableViewCell.nibName, bundle: nil) tableView.register(foodCellNib, forCellReuseIdentifier: FoodTableViewCell.reuseIdentifier)
  31. 31. extension UITableView { func register<T: UITableViewCell>(_: T.Type) where T: ReusableView, T: NibLoadableView { let nib = UINib(nibName: T.nibName, bundle: nil) register(nib, forCellReuseIdentifier: T.reuseIdentifier) } }
  32. 32. let foodCellNib = UINib(nibName: "FoodTableViewCell", bundle: nil) tableView.register(foodCellNib, forCellReuseIdentifier: "FoodTableViewCell")
  33. 33. tableView.register(FoodTableViewCell.self)
  34. 34. extension UITableView { func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: ReusableView { guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath as IndexPath) as? T else { fatalError("Could not dequeue cell with identifier: (T.reuseIdentifier)") } return cell } }
  35. 35. guard let cell = tableView.dequeueReusableCell(withIdentifier: β€œFoodTableViewCell", forIndexPath: indexPath) as? FoodTableViewCell else { fatalError("Could not dequeue cell with identifier: FoodTableViewCell") }
  36. 36. let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as FoodTableViewCell
  37. 37. if indexPath.row == 0 { return tableView.dequeueReusableCell(forIndexPath: indexPath) as DesertTableViewCell } return tableView.dequeueReusableCell(forIndexPath: indexPath) as FoodTableViewCell
  38. 38. iOS Cell Registration & Reusing with Swift Protocol Extensions and Generics medium.com/@gonzalezreal
  39. 39. Protocol-Oriented Segue Identifiers in Swift natashatherobot.com
  40. 40. POP Networking
  41. 41. struct FoodService { func get(completionHandler: Result<[Food]> -> Void) { // make asynchronous API call // and return appropriate result } }
  42. 42. enum Result<T> { case Success(T) case Failure(Error) }
  43. 43. struct FoodService { func get(completionHandler: (Result<[Food]>) -> Void) { // make asynchronous API call // and return appropriate result } }
  44. 44. // FoodLaLaViewController var dataSource = [Food]() { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() getFood() } private func getFood() { FoodService().get() { [weak self] result in switch result { case .Success(let food): self?.dataSource = food case .Failure(let error): self?.showError(error: error) } } }
  45. 45. View Controller Tests?!!! 😱
  46. 46. // FoodLaLaViewController var dataSource = [Food]() { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() getFood() } private func getFood() { FoodService().get() { [weak self] result in switch result { case .Success(let food): self?.dataSource = food case .Failure(let error): self?.showError(error) } } }
  47. 47. // FoodLaLaViewController func getFood(fromService service: FoodService) { service.getFood() { [weak self] result in // handle result } }
  48. 48. // FoodLaLaViewControllerTests func testFetchFood() { viewController.getFood(fromService: FoodService()) // πŸ€” now what? }
  49. 49. struct FoodService { func get(completionHandler: (Result<[Food]>) -> Void) { // make asynchronous API call // and return appropriate result } }
  50. 50. protocol Gettable { associatedtype T func get(completionHandler: (Result<T>) -> Void) }
  51. 51. struct FoodService: Gettable { func get(completionHandler: (Result<[Food]>) -> Void) { // make asynchronous API call // and return appropriate result } }
  52. 52. // FoodLaLaViewController override func viewDidLoad() { super.viewDidLoad() getFood(fromService: FoodService()) } func getFood<S: Gettable>(fromService service: S) where S.T == [Food] { service.get() { [weak self] result in switch result { case .Success(let food): self?.dataSource = food case .Failure(let error): self?.showError(error) } } }
  53. 53. // FoodLaLaViewControllerTests class Fake_FoodService: Gettable { var getWasCalled = false func get(completionHandler: (Result<[Food]>) -> Void) { getWasCalled = true completionHandler(Result.Success(food)) } }
  54. 54. // FoodLaLaViewControllerTests func testFetchFood() { let fakeFoodService = Fake_FoodService() viewController.getFood(fromService: fakeFoodService) XCTAssertTrue(fakeFoodService.getWasCalled) XCTAssertEqual(viewController.dataSource.count, food.count) XCTAssertEqual(viewController.dataSource, food) }
  55. 55. Update: View Controller Data Injection with Storyboards and Segues in Swift natashatherobot.com
  56. 56. Protocols with Associated Types Alexis Gallagher 2015.funswiftconf.com
  57. 57. 😎😎😎
  58. 58. Practical POP β€’ View β€’ (UITable)ViewController β€’ Networking
  59. 59. Beyond Crusty: Real-World Protocols Rob Napier thedotpost.com
  60. 60. Blending Cultures: The Best of Functional, Protocol-Oriented, and Object-Oriented Programming Daniel Steinberg realm.io
  61. 61. T H A N K Y O U ! β€’ @NatashaTheRobot πŸ€– β€’ NatashaTheRobot.com β€’ This Week in Swift Newsletter β€’ Swift Jobs β€’ tryswift.co πŸ₯#πŸŽ‰ β€’ @NatashaTheNomad %
  62. 62. @NatashaTheRobot

Γ—