GithubHelp home page GithubHelp logo

session-3's Introduction

Hack Sprint Session 3 README

Slides: https://docs.google.com/presentation/d/1Mhj2pIHINDBj-jBvQNyKM6AApOk-yffR7wGLuSP4PJM/edit?usp=sharing

Table of Contents

Getting Started

  1. We're going to provide some boilerplate code for this session's project. Navigate to this GitHub repo.

    The boilerplate code contains:

    • A file JSONHelperFunctions.swift that contains functions to parse a JSON file and extra data about each Pokemon.
    • A file PokemonTableViewController.swift with function skeletons (to be filled out) that serves as the code for the main Table View Controller as a whole.
      • This file contains a helper function named loadImageFromURL() that takes in a URL and a UIImageView and asynchronously fetches the image at the URL and sets it as the UIImageView's image.
    • A file PokemonTableViewCell.swift which contains an empty class that serves as the code for each individual cell in the Table View.
    • A file Main.storyboard which contains a UITableViewController of type PokemonTableViewController, whose table cells are of type PokemonTableViewCell.
    • A Pokeball image located in Assets.xcassets.
    • A file pokedex.json containing data about each Pokemon in JSON format.
    • A file info.plist that has been updated to allow us to make requests to URLs that begin with just http (as opposed to https).
  2. Click on the "Clone or Download" button on the right side of the page and selected "Download ZIP."


  1. Open the folder you just downloaded; it should be called session-3-master.
  2. Open the folder PrettyGoodPokedexStarter.
  3. Double-click the file PrettyGoodPokedex.xcodeproj to open the project in Xcode.
  1. Using the Project Navigator on the left side of Xcode, open the Interface Builder by clicking on the Main.storyboard file.
  2. Click on the Table View (i.e. the gray area, not the Prototype Cell).
  3. On the right side of the screen, open the Size Inspector by clicking the ruler icon, ensuring that it has a header that says Table View. If it says View Controller, click on the Table View again and it should change.


  1. Locate the Row Height field at the top of the Size Inspector and set it to 50. The "Automatic" box should become unchecked.


  1. It may be helpful to zoom in, using pinch-drag, for this next part.
  2. In the bottom right of the screen, ensuring that the third tab is selected, scroll until you find the Image View element.


  1. Drag an Image View into the Prototype Cell (i.e. the small white region at the top of the View Controller) and arrange it similar to the image below:


  1. Returning to the bottom right side of Xcode, scroll up until you find the Label element.


  1. Drag a Label into the Prototype Cell and arrange it similar to the image below:


  1. Select the Image View again.
  2. On the right side of the screen, open the Attributes Inspector by clicking on the icon to the left of the ruler icon.
  3. Locate the Image field at the top of the Inspector and use the drop-down menu to change it to the Pokeball image.


  1. With the Image View still selected, click the "Add New Constraints" button near the bottom right of the screen.
  2. Set the top, left, and bottom margins to 0, and set the right margin to 10. The red lines should now be solid instead of dashed.
  3. Set the Width to 50. The box next to "Width" should now be checked.
  4. Click "Add 4 Constraints".


  1. Select the Label.
  2. Click on the button to the left of the "Add New Constraints" button.
  3. Check the "Vertically in Container" box.
  4. Click "Add 1 Constraint".


We're going to add IBOutlets manually without the use of the Assistant editor.

  1. Using the Project Navigator on the left side of Xcode, select PokemonTableViewCell.swift.

  2. Inside the class declaration, check that the following code is there:

    @IBOutlet var pokemonImageView: UIImageView!
    @IBOutlet var nameLabel: UILabel!
    


  1. Return to the Interface Builder by selecting Main.storyboard in the Project Navigator.
  2. Click on the Prototype Cell (white area containing the UI elements we just dragged in). You can check that you've selected the right object by opening either the Attributes Inspector or Size Inspector and verifying that the top header says Table View Cell.
  3. Open the Connections Inspector by clicking on the arrow icon to the right of the ruler icon.
  4. Locate pokemonImageView and nameLabel in the Outlets section. If you do not see them, you may need to go back into PokemonTableViewCell.swift and save the file (cmd+s).


  1. If you hover over the circle to the right of pokemonImageView you should see a plus sign appear within it. Click on the circle and drag to the Image View (with the Pokeball) that we added earlier.
  2. Click on the circle to the right of nameLabel and drag to the Label that we added earlier.
  3. If you erroneously connect to the wrong elements, simply tap the "x" that appears in the outlet (seen below):


We're all set to begin coding!

Coding in Swift

We're going to create a custom Pokemon class that encapsulates all of the data that we need to know about a Pokemon.

  1. At the top of your screen, select File > New > File.


  1. Double click on "Swift File".
  2. Name it "Pokemon" and click Create. You should now be looking at a new file named Pokemon.swift.


  1. Create a Pokemon class by adding the following code to the file:

    class Pokemon {
        
        var name: String
        var imageURL: URL
        var type: String
        var weight: String
        
    }
    
  2. Add an initializer inside Pokemon class, below all of the properties we just declared:

    init(name: String, imageURL: String, type: String, weight: String) {
            self.name = name
            self.imageURL = URL(string: imageURL)!
            self.type = type
            self.weight = weight
    }
    

Checkpoint: You should now be able to build and run your app. You won't see any cells though; let's add those next!

  1. Return to the Project Navigator and click on the PokemonTableViewController.swift file.

  2. Add a pokemonArray property above all of the function declarations, which is initialized to an empty array of Pokemon objects. This array will be used to store all of the Pokemon data.

    var pokemonArray = [Pokemon]()
    
  3. Add the following code to viewDidLoad():

    pokemonArray = getPokemon()
    
  4. Our Table View will have only one section, so change the numberOfSections(in:) function to return 1:

    override func numberOfSections(in tableView: UITableView) -> Int {
            return 1
    }
    
  5. The number of cells in our Table View should be equal to the number of Pokemon we have, so change the tableView(_:numberOfRowsInSection:) function:

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return pokemonArray.count
    }
    

Now for the most complex function regarding UITableViews. The tableView(_:cellForRowAt:) function returns the UITableViewCell object that should be shown at a given row:

  1. Return to the Interface Builder by selecting the Main.storyboard file via the Project Navigator.
  2. Click on the Prototype Cell and open the Attributes Inspector by clicking on the icon to the left of the ruler, ensuring that the header says Table View Cell.
  3. Locate the Identifier field two rows from the top and give it a value of "PokemonCell".
  4. Press Enter.


  1. Return to PokemonTableViewController via the Project Navigator.

  2. Replace tableView(_:cellForRowAt:) with the following code:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            
    	guard let cell = tableView.dequeueReusableCell(withIdentifier: "PokemonCell") as? PokemonTableViewCell else {
    		fatalError("Cell is not of type PokemonTableViewCell")
    	}
            
        let pokemon = pokemonArray[indexPath.row]
            
        cell.pokemonImageView.image = UIImage(named: "Pokeball")
    	loadImageFromURL(pokemon.imageURL, into: cell.pokemonImageView)
        cell.nameLabel.text = pokemon.name
            
        return cell
        
    }
    

Checkpoint: Build and run your app to see all of the Pokemon!

  1. Declare a new property just underneath pokemonArray:
var pokemonArray = [Pokemon]()
var modalView: UIView? = nil
  1. Add the following code to the class:
	override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // Get the Pokemon object
        let pokemon = pokemonArray[indexPath.row]
        
        // Size of the screen
        let screen = UIScreen.main.bounds
        
        // Create a 300x200 modal view with a light gray background color. Place it in the center
        // of the screen.
        let newModalView = UIView()
        newModalView.frame.size = CGSize(width: 300, height: 200)
        newModalView.center = CGPoint(x: screen.width/2, y: screen.height/2)
        newModalView.backgroundColor = UIColor.lightGray
        
        // Create a UILabel whose text is "Type: pokemon.type". Call sizeToFit() to automatically
        // size the UILabel. Vertically center it within the modal view but set it's centerY to
        // be the top fourth of the modal View.
        let typeLabel = UILabel()
        typeLabel.text = "Type: " + pokemon.type
        typeLabel.sizeToFit()
        typeLabel.center = CGPoint(x: newModalView.center.x, y: newModalView.frame.height * 0.25)
        
        // Create a UILabel whose text is "Weight: pokemon.weight". Call sizeToFit() to
        // automatically size it. Vertically center it within the modal view but set it's
        // centerY to be the bottom fourth of the modal View.
        let weightLabel = UILabel()
        weightLabel.text = "Weight: " + pokemon.weight
        weightLabel.sizeToFit()
        weightLabel.center = CGPoint(x: newModalView.center.x, y: newModalView.frame.height * 0.75)
        
        // Create a UIButton that has "X" as its title and call sizeToFit() to automatically
        // size it. Set it's center to be the top left corner of the modal view. When the user
        // taps and releases on the button, perform the selector (i.e. function) closeModalView()
        // which is declared below.
        let closeButton = UIButton()
        closeButton.setTitle("X", for: .normal)
        closeButton.sizeToFit()
        closeButton.center = CGPoint(x: 20, y: 20)
        closeButton.addTarget(self, action: #selector(closeModalView), for: .touchUpInside)
        
        // Add the two labels and the close button to the modal view.
        newModalView.addSubview(typeLabel)
        newModalView.addSubview(weightLabel)
        newModalView.addSubview(closeButton)
        
        // Set the modal view's transparency to 0 (hidden) and add it to the tableView.
        newModalView.alpha = 0
        self.tableView.superview?.addSubview(newModalView)
        
        // Hold on to a reference of the modal view we just created so we can refer to/access it
        // in another function
        modalView = newModalView
        
        // Use the UIView.animate function to perform animations; inside the animations
        // parameter you pass in a block of code that contains what you want the final state
        // of the objects to be after the animation. This code reads, in a duration of 0.25s
        // linearly change the value of newModalView.alpha from whatever it currently is (in
        // our case, 0) to 1.
        UIView.animate(withDuration: 0.25, animations: {
            newModalView.alpha = 1
        })
        
        // Disable tableView for now.
        tableView.isScrollEnabled = false
        tableView.allowsSelection = false
        
    }
    
    // Function called when we tap the close button.
    @objc func closeModalView() {
        
        if let unwrappedModalView = modalView {
            
            // Fade out the modal view. The completion: parameter accepts a block of code that
            // will be executed after the animation completes. We want to remove the modal view
            // from the table view and also set our modalView property to nil.
            UIView.animate(withDuration: 0.25, animations: {
                unwrappedModalView.alpha = 0
            }, completion: { (success) in
                unwrappedModalView.removeFromSuperview()
                self.modalView = nil
            })
            
            // Reenable the table view.
            tableView.isScrollEnabled = true
            tableView.allowsSelection = true
            
        }
        
    }

do it to win a prize woohoo

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.