Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Daniel Burke: Scratch that: Building an app in Swift

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
March 01, 2017

Daniel Burke: Scratch that: Building an app in Swift

Video: https://www.youtube.com/watch?v=HtBSvPFaCWE&feature=youtu.be

Title: Scratch that: Building an app in Swift

Speaker: Daniel Burke is a Software Engineer at Yelp building the next phase of Yelp's messaging platform. Before this, Daniel managed a team of iOS & Android developers at ForRent.com in Norfolk, VA as well as a team of R&D developers focused on leveraging new and emerging technologies. Before DE, Daniel was a web and iOS developer at Grow in Norfolk, VA, working with companies like Google, Burberry, and RedBull. Daniel is a leading member of ColorCoded, a group within Yelp focused on fostering diversity in the engineering community through mentorship, workshops, and public speaking. Daniel enjoys basketball, running, hiking, scuba-diving, and skiing and is the proud father of a 4-year-old daughter and a 10-year-old son.

Abstract: There are plenty of reasons why you may be considering Swift for your next project. You may be starting a new venture, rebuilding an existing app, learning Swift as a new language, or even just beginning your adventure as a programmer. Let's talk about these scenarios and learn by doing. In this talk/workshop, we'll build the core features of a basic app and cover the most important elements of building an iOS app in Swift from scratch. Bring your Mac with the latest version of Xcode installed and be ready for fast paced instruction and witty banter.

Twitter Link: https://twitter.com/d2burke

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

March 01, 2017
Tweet

Transcript

  1. Daniel Burke dburke@yelp | @d2burke Scratch That Building an app

    in Swift
  2. • Intro *Lite • Setting up • Building the app

    • Optimizations (Maybe?) Agenda
  3. • Software Engineer @ Yelp ◦ Messaging ◦ Current: Obj-C

    -> Swift • Eng. Mgr @ForRent.com ◦ Framework -> Swift ◦ Swift -> Obj-C ◦ Swift From Scratch Me Daniel Burke
  4. Yelp’s Mission Connecting people with great local businesses.

  5. • How many have shipped an app as the primary

    or only engineer? • How many have shipped an app as a part of a team? • How many of you are new to programming within the last year? You The Audience
  6. • Xcode • File Structure • Version Control • Dependencies

    Setting up First things first
  7. • New Project • Single View Application • Name: “Matchup”

    • Language: Swift • Git: Absolutely Setting up Xcode
  8. Setting up Xcode

  9. • Project Navigator (File Structure) ◦ ** delete ViewController [“Move

    to Trash”] • Debug Area (Console) • Utilities (Inspectors & Attributes) Setting up Xcode
  10. • By Class Type (MVC, Utils) • By Feature/Team (Feature,

    Auth Flow) • Favor new files Setting up File Structure
  11. • Use branches • Commit early and often • Push

    complete features Setting up Version Control
  12. • Don’t reinvent the wheel • Carefully vet 3rd party

    libraries • Pay respects via attribution if you ship Setting up Dependencies
  13. $ vim Podfile --- source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks!

    target 'Matchup' do pod 'AlamofireImage', '~> 3.1' end --- $ pod install Analyzing dependencies Downloading dependencies Using Alamofire (4.3.0) ... Close Xcode Open *.xcworkspace
  14. Setting up Open the *xcworkspace

  15. • Player List (type inferencing, self-invoking closures, extensions, guard) •

    Matchup Results (custom init(), string interpolation) • Login View (storyboard layouts, protocols) Building the app
  16. • Add some views • Install some AL constraints •

    Wire up our TableView • Wire up our Compare button Building the app Player List
  17. ** Create Controller/PlayersViewController.swift // 1. In AppDelegate.swift > application:didFinishLaunching... let

    playersViewController: PlayersViewController() playersViewController.view.backgroundColor = .white let navController = UINavigationController(rootViewController.. navController.navigationBar.isTranslucent = false window?.rootViewController = navConroller window?.makeKeyAndVisible() Set up initial view Player List
  18. // 1. Add button and function lazy var compareButton: UIButton

    = {... // 2. var disabledGray = UIColor.lightGray.withAlphaComponent(0.5) ** Can’t access `self` until it has been initialized ** Here we can use a lazy var - waits until var is accessed :) Add some views Player List
  19. // 3. var playerTableView: UITableView = {... // 4. Add

    views and set delegate view.addSubview(playerTableView) … ** The compiler is going to be annoying until we fully conform to the UITableView delegate, so do let’s ** Create Model/Player.swift Copy Pasta: http://pastebin.com/hTXZ3p10 Add some views (cont’d) Player List
  20. // 1. func installConstraints() { // 2. let views:[String:UIView]=[“compareButton”:compareButton… compareButton.translatesAutoresizingMask…

    let constraints = [NSLayoutConstraint.constraints… NSLayoutConstraint.activate(constraints.flatMap({ $0 })) } // 3. installConstraints() Add some constraints Player List Build (and run) CMD + R
  21. ** Create a Set to hold our selected cell indexPaths

    var checkedCells = Set<IndexPath>() // 1. Get player for cell let player = Player(dict: players[indexPath.row]) // 2. Configure our cell cell.textLabel?.text = player?.name... if checkedCells.count == 2 { cell.isUserInteractionEnabled = (isSelected) ? true : ... cell.textLabel?.textColor = (isSelected) ? .black : ... Configure our TableView cells Player List
  22. // 1. extension SearchViewController: UITableViewDelegate { func tableView(_ tableView: UITableView,

    didSelectRowAt... if checkedCells.contains(indexPath) {... // 2. let color: UIColor = (checkedCells.count == 2) ? .white... let backgroundColor = (checkedCells.count == 2) ? .blue... compareButton.backgroundColor = backgroundColor ... //3. playerTableView.reloadData() Handle selecting players Player List Build (and run) CMD + R
  23. func didTapCompareButton(button: UIButton) { // 1. Cast Set to Array

    let indexPaths = Array(checkedCells) // 2. Validate guard checkedCells.count == 2, let indexPath1 = indexPaths.first, let indexPath2 = indexPaths.last, let player1 = Player(dict: players[indexPath1.row]), let player2 = Player(dict: players[indexPath2.row]) else { return } ... Compare Players Func Player List
  24. None
  25. Can’t get nil pointer exceptions... If you don’t point at

    nils
  26. ** Create Controller/MatchupViewController.swift view.backgroundColor = .white // 1. Add player

    vars let player1: Player let player2: Player // 2. Add custom init() init(player1: Player, player2: Player) { self.player1 = player1 self.player2 = player2 super.init(nibName: nil, bundle: nil) ... Set up match-up view Matchup View
  27. ** Back in Controller/PlayersViewController.swift // 3. Create Matchup View with

    custom init() let matchupView = MatchupViewController( player1: player1, player2: player2 ) // 4. Push view onto the stack self.navigationController?.pushViewController(matchupView… ** Compare Players Func (cont’d) Player List Build (and run) CMD + R
  28. ** Back in Controller/MatchupViewController.swift // 1. Add name labels let

    player1Label: UILabel = { ... let player2Label: UILabel = { ... // 2. Update our title let player1Wins = player1.rating > player2.rating let winnerName = player1Wins ? player1.name : player2.name title = "\(winnerName) Wins!" Copy Pasta: http://pastebin.com/BhD6G8Vh Add some views Matchup View
  29. ** Create View/UIImageView+Loader.swift // 1. Load image asynchronously Copy Pasta:

    http://pastebin.com/sxhst8R8 Load some images Matchup View
  30. // 1. Set image with result of async call ...

    if let image = response.result.value { self.image = image } ... Load some images (cont’d) Matchup View
  31. // 2. Call this function on our images override func

    viewWillAppear(_ animated: Bool) { player1ImageView.loadImage(imageURL: player1.imageURL) player2ImageView.loadImage(imageURL: player2.imageURL) } Load some images (cont’d) Matchup View Build (and run) CMD + R
  32. • Player List (type inferencing, self-invoking closures, extensions, guard) •

    Matchup Results (custom init(), string interpolation) • Login View (storyboard layouts, protocols) Building the app
  33. ** Create Controller/LoginViewController.swift view.backgroundColor = .white ** Set Storyboard view

    class AND Storyboard ID Set up login view Log In View
  34. ** Drag out a UIView, 2 UIButtons, & UITextField Set

    up login view (cont’d) Log In View
  35. ** Position & create constraints Set up login view (cont’d)

    Log In View
  36. ** Connect IBOutlets Set up login view (cont’d) Log In

    View
  37. // 1. Create delegate protocol LoginViewControllerDelegate { func didLogin() }

    ... // 2. Call delegate method @IBAction func login(_ sender: Any) { delegate?.didLogin() } Set up login view (cont’d) Log In View
  38. ** Back in Controller/PlayersViewController.swift // 3. Conform to LoginViewControllerDelegate extension

    PlayersViewController: LoginViewControllerDelegate { func didLogin() { UserDefaults.standard.set("yes", forKey: "LoggedIn") dismiss(animated: true, completion: nil) } } Set up login view (cont’d) Log In View
  39. ** Back in Controller/PlayersViewController.swift // 4. In viewWillAppear: guard let

    _ = UserDefaults.standard.object(forKey: "LoggedIn") else { presentLogin() } Copy Pasta: http://pastebin.com/vTmAUhi5 Set up login view (cont’d) Log In View Build (and run) CMD + R
  40. ** Back in Controller/PlayersViewController.swift // BONUS. Add a Log Out

    button navigationItem.rightBarButtonItem = UIBarButtonItem(title:... // 5. Add logOut func func logOut() { UserDefaults.standard.remove(forKey: "LoggedIn") presentLogin() } Set up login view (cont’d) Log In View
  41. Building the app Yay!

  42. • Configuring views with ViewModels (buttons, cells, fields, etc) •

    Moving Delegate/Datasource code to separate files Optimizations
  43. Any Questions? https://github.com/d2burke/matchup