$30 off During Our Annual Pro Sale. View Details »

Swift User Group - April 2016: Building Fabric.app in Swift

Swift User Group - April 2016: Building Fabric.app in Swift

Collection to tidbits about the things I learned while building the Fabric app.

Javier Soto

April 14, 2016
Tweet

More Decks by Javier Soto

Other Decks in Programming

Transcript

  1. Building Fabric.app in Swift
    "Building Fabric.app in Swift" - Javier Soto. April 2016 1

    View Slide

  2. Intro
    @Javi
    "Building Fabric.app in Swift" - Javier Soto. April 2016 2

    View Slide

  3. "Building Fabric.app in Swift" - Javier Soto. April 2016 3

    View Slide

  4. Outline
    4 What is Fabric.app?
    4 Tools used
    4 Architecture
    4 Better with Swift
    4 Error reporting
    "Building Fabric.app in Swift" - Javier Soto. April 2016 4

    View Slide

  5. What is Fabric.app?
    "Building Fabric.app in Swift" - Javier Soto. April 2016 5

    View Slide

  6. What is Fabric.app?
    "Building Fabric.app in Swift" - Javier Soto. April 2016 6

    View Slide

  7. What is Fabric.app?
    "Building Fabric.app in Swift" - Javier Soto. April 2016 7

    View Slide

  8. Tools
    "Building Fabric.app in Swift" - Javier Soto. April 2016 8

    View Slide

  9. Dependency management
    "Building Fabric.app in Swift" - Javier Soto. April 2016 9

    View Slide

  10. Dependency management
    4 SSL Pinning
    4 Keychain
    4 1Password integration
    4 Graphs
    4 Networking, caching
    "Building Fabric.app in Swift" - Javier Soto. April 2016 10

    View Slide

  11. Dependency management
    4 CocoaPods
    4 Carthage
    "Building Fabric.app in Swift" - Javier Soto. April 2016 11

    View Slide

  12. CocoaPods
    4 More widely adopted
    4 Less work to integrate frameworks
    4 Easily link some frameworks only in Debug
    "Building Fabric.app in Swift" - Javier Soto. April 2016 12

    View Slide

  13. Carthage
    4 Precompilation == Speed
    "Building Fabric.app in Swift" - Javier Soto. April 2016 13

    View Slide

  14. Swift Package Manager
    "Building Fabric.app in Swift" - Javier Soto. April 2016 14

    View Slide

  15. Interface Builder
    "Building Fabric.app in Swift" - Javier Soto. April 2016 15

    View Slide

  16. AutoLayout
    "Building Fabric.app in Swift" - Javier Soto. April 2016 16

    View Slide

  17. AutoLayout
    "Building Fabric.app in Swift" - Javier Soto. April 2016 17

    View Slide

  18. Storyboards
    "Building Fabric.app in Swift" - Javier Soto. April 2016 18

    View Slide

  19. UIStoryboard
    class UIStoryboard {
    func instantiateViewControllerWithIdentifier(_ identifier: String) -> UIViewController
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 19

    View Slide

  20. UIStoryboard
    let vc = mainStoryboard.instantiateViewControllerWithIdentifier("ApplicationOverviewID") as! ApplicationOverviewVC
    vc.userSession = ...
    vc.applicationID = ...
    "Building Fabric.app in Swift" - Javier Soto. April 2016 20

    View Slide

  21. UIStoryboard
    final class ApplicationOverviewVC {
    // I hope you like "!"s...
    var userSession: UserSession!
    var applicationID: String!
    func viewDidLoad() {
    super.viewDidLoad()
    self.userSession.foo()
    }
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 21

    View Slide

  22. Storyboards
    final class ApplicationOverviewVC {
    let userSession: UserSession
    let applicationID: String
    init(userSession: UserSession, applicationID: String) {
    self.userSession = userSession
    self.applicationID = applicationID
    super.init(nibName: ..., bundle: ...)
    }
    func viewDidLoad() {
    super.viewDidLoad()
    // Compile-time guarantee of object fully initialized
    self.userSession.foo()
    }
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 22

    View Slide

  23. Fastlane
    "Building Fabric.app in Swift" - Javier Soto. April 2016 23

    View Slide

  24. Fastlane
    - https://github.com/fastlane/examples
    "Building Fabric.app in Swift" - Javier Soto. April 2016 24

    View Slide

  25. ReactiveCocoa
    "Building Fabric.app in Swift" - Javier Soto. April 2016 25

    View Slide

  26. ReactiveCocoa
    self.accountService.muteAllNotifications(untilTime: date)
    "Building Fabric.app in Swift" - Javier Soto. April 2016 26

    View Slide

  27. ReactiveCocoa
    self.accountService.muteAllNotifications(untilTime: date)
    .continueWhenApplicationIsBackgrounded(taskName: "Muting notifications")
    "Building Fabric.app in Swift" - Javier Soto. April 2016 27

    View Slide

  28. Tools
    "Building Fabric.app in Swift" - Javier Soto. April 2016 28

    View Slide

  29. Architecture
    "Building Fabric.app in Swift" - Javier Soto. April 2016 29

    View Slide

  30. Architecture
    FabricAPI.framework
    "Building Fabric.app in Swift" - Javier Soto. April 2016 30

    View Slide

  31. Architecture
    4 Massive View Controllers
    4 View Models
    4 Glue-code View Controllers
    4 Table View Data sources
    "Building Fabric.app in Swift" - Javier Soto. April 2016 31

    View Slide

  32. Architecture
    GenericTableViewDataSource
    "Building Fabric.app in Swift" - Javier Soto. April 2016 32

    View Slide

  33. Architecture
    GenericTableViewDataSource
    protocol TableSectionType {
    associatedtype AssociatedTableRowType: TableRowType
    var rows: [AssociatedTableRowType] { get }
    var title: String? { get }
    }
    protocol TableRowType { }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 33

    View Slide

  34. Architecture
    GenericTableViewDataSource
    final class GenericTableViewDataSource
    SectionType: TableSectionType,
    RowType: TableRowType
    where SectionType.AssociatedTableRowType == RowType,
    SectionType: Equatable,
    RowType: Equatable>: NSObject, UITableViewDataSource
    "Building Fabric.app in Swift" - Javier Soto. April 2016 34

    View Slide

  35. Architecture
    GenericTableViewDataSource
    enum ProjectIssueRow: TableRowType, Equatable {
    case Loading
    case NoIssues
    case ErrorLoadingIssues
    case ProjectIssue(Issue)
    }
    return GenericTableViewDataSource(
    tableView: tableView,
    tableViewData: observableProperty, // Observable
    computeSections: { elements in ... }, /// Pure function from `Elements` to `[SectionType]`
    configureRow: { row, indexPath in ... } /// Function from `RowType` to `UITableViewCell`
    )
    "Building Fabric.app in Swift" - Javier Soto. April 2016 35

    View Slide

  36. Better with Swift
    "Building Fabric.app in Swift" - Javier Soto. April 2016 36

    View Slide

  37. Better with Swift
    4 Nullability
    4 Type-safe JSON parsing
    4 Code generation
    "Building Fabric.app in Swift" - Javier Soto. April 2016 37

    View Slide

  38. Nullability
    "Building Fabric.app in Swift" - Javier Soto. April 2016 38

    View Slide

  39. "Building Fabric.app in Swift" - Javier Soto. April 2016 39

    View Slide

  40. Nullability
    final class ApplicationListViewController: BaseFabricTableViewController
    "Building Fabric.app in Swift" - Javier Soto. April 2016 40

    View Slide

  41. Nullability
    final class ApplicationListViewController: BaseFabricTableViewController {
    override viewDidLoad() {
    super.viewDidLoad()
    let session = UserSession.currentUserSession
    if let session = session session {
    session.requestApplications()...
    }
    // or...
    session!.requestApplications()...
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 41

    View Slide

  42. Nullability
    final class ApplicationListViewController: BaseFabricTableViewController {
    init(viewModel: ApplicationListViewModel)
    }
    final class ApplicationListViewModel {
    init(fabricAPI: AuthenticatedFabricAPI)
    }
    public final class AuthenticatedFabricAPI {
    public init(authResponse: AuthResponse)
    }
    public final class AuthResponse {
    let accessToken: String
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 42

    View Slide

  43. "Building Fabric.app in Swift" - Javier Soto. April 2016 43

    View Slide

  44. Nullability
    final class ApplicationListViewModel {
    var applications: [Application]?
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 44

    View Slide

  45. Nullability
    enum DataLoadState {
    case Loading
    case Failed
    case Loaded(T)
    }
    final class ApplicationListViewModel {
    var applications: DataLoadState<[Application]> = .Loading
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 45

    View Slide

  46. Type-safe JSON parsing
    "Building Fabric.app in Swift" - Javier Soto. April 2016 46

    View Slide

  47. JSON Parsing Anti-Patterns
    public struct Application {
    public var ID: String?
    public var name: String?
    public var bundleIdentifier: String?
    public mutating func decode(j: [String: AnyObject]) {
    self.ID = j["id"] as? String
    self.name = j["name"] as? String
    self.bundleIdentifier = j["identifier"] as? String
    }
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 47

    View Slide

  48. JSON Parsing Anti-Patterns
    public struct Application {
    public let ID: String
    public let name: String
    public let bundleIdentifier: String
    public static func decode(j: [String: AnyObject]) -> Application? {
    guard let ID = j["id"] as? String,
    let name = j["name"] as? String,
    let bundleIdentifier = j["identifier"] as? String else { return nil }
    return Application(
    ID: ID,
    name: name,
    bundleIdentifier: bundleIdentifier
    )
    }
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 48

    View Slide

  49. Type-safe JSON parsing
    import Decodable /// https://github.com/Anviking/Decodable
    public struct Application: Decodable {
    public let ID: String
    public let name: String
    public let bundleIdentifier: String
    public static func decode(j: AnyObject) throws -> Application {
    return try Application(
    ID: j => "id",
    name: j => "name",
    bundleIdentifier: j => "identifier"
    )
    }
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 49

    View Slide

  50. Code Generation
    "Building Fabric.app in Swift" - Javier Soto. April 2016 50

    View Slide

  51. Code Generation
    /// Swift < 2.2
    UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: Selector("buttonTapped"))
    // Swift 2.2
    UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: #selector(ViewController.buttonTapped))
    "Building Fabric.app in Swift" - Javier Soto. April 2016 51

    View Slide

  52. Code Generation
    super.init(nibName: "ViewControllerNibName", bundle: nil)
    let nib = UINib(nibName: "NibName", bundle: nil)
    tableView.registerNib(nib, forCellReuseIdentifier: "ReuseIdentifier")
    let cell = tableView.dequeueReusableCellWithIdentifier("ReuseIdentifier", forIndexPath: indexPath) as! MyTableViewCell
    let image = UIImage(named: "ImageName")!
    "Building Fabric.app in Swift" - Javier Soto. April 2016 52

    View Slide

  53. Code Generation: R.swift
    https://github.com/mac-cain13/R.swift
    "Building Fabric.app in Swift" - Javier Soto. April 2016 53

    View Slide

  54. Code Generation: R.swift
    https://github.com/mac-cain13/R.swift
    4 Nibs
    4 Reuse Identifiers
    4 Image names in asset catalogs
    4 Other file names in the bundle
    "Building Fabric.app in Swift" - Javier Soto. April 2016 54

    View Slide

  55. Code Generation: R.swift
    https://github.com/mac-cain13/R.swift
    super.init(nibResource: R.nib.myViewController)
    class MyTableViewCell: UITableViewCell, ReusableNibTableViewCell {
    /// This will even fail to compile if it's not the right cell
    static let nibResource = R.nib.myTableViewCell
    }
    tableView.registerReusableNibCell(MyTableViewCell)
    let cell = MyTableViewCell.dequeueFromTableView(tableView, indexPath)
    let image = R.image.imageName
    "Building Fabric.app in Swift" - Javier Soto. April 2016 55

    View Slide

  56. Error Reporting
    "Building Fabric.app in Swift" - Javier Soto. April 2016 56

    View Slide

  57. Error Reporting
    do {
    try fileManager.createDirectoryAtPath(path, withIntermediateDirectories: true, attributes: nil)
    /// ...
    }
    catch {
    print("Error: \(error)")
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 57

    View Slide

  58. Error Reporting
    do {
    try fileManager.createDirectoryAtPath(path, withIntermediateDirectories: true, attributes: nil)
    /// ...
    }
    catch {
    Crashlytics.sharedInstance().recordError(error, withAdditionalUserInfo: userInfo)
    }
    "Building Fabric.app in Swift" - Javier Soto. April 2016 58

    View Slide

  59. Error Reporting
    "Building Fabric.app in Swift" - Javier Soto. April 2016 59

    View Slide

  60. Questions?
    4 @Javi
    4 [email protected]
    4 [email protected]
    "Building Fabric.app in Swift" - Javier Soto. April 2016 60

    View Slide

  61. Thanks !
    "Building Fabric.app in Swift" - Javier Soto. April 2016 61

    View Slide