Skip to content

Latest commit

 

History

History
209 lines (147 loc) · 10 KB

Workshop1-Creation.md

File metadata and controls

209 lines (147 loc) · 10 KB

Please feel free to suggest changes by raising a Pull Request on this document, or opening an Issue!


Workshop 1 - Creation

Today we're going to create our very own news viewing app! 🎉 Don't worry, we'll be guided through each step, and we've pre-written some of the more complicated code so we can get our app up and running in just one session.

Let's get to it! 🔨

1. Running an app

  1. Find Xcode on your machine and launch it alt text

  2. Create a new project using the option Single View App alt text

  3. Update the following fields:

    1. Product name: Something like 'bestest-news-reader'
    2. Team Leave this set to 'none'
    3. Organization Name: Something like Codebar
    4. Organization Identifier: Something like com.codebar
    5. Language: Swift :awesome:
    6. Use Core Data: Leave this unchecked
    7. Include Unit Tests: Uncheck this
    8. Include UI Tests: Uncheck this <img src=/3.png" title="Fill in the fields according to instructions" alt="alt text">
  4. Run the project by hitting the Play button up top

    alt text
  5. Another application will start - the Simulator. This application lets us see how our iOS app looks without needing a physical device. Given that we haven't made any changes, we should see an empty white screen. Amazing - we're now iOS developers!! ❤️

    alt text
  6. Now, open up the file Main.storyboard. This is the file where we represent the layout of our app. It's a great tool to use because it lets us easily visualise our app.

    alt text
  7. A label is used to display non-interactive text. That is, our users can't change the text in this label, but we can. 👍 Create a label in the Main.storyboard file and write the word Codebar inside.

    Alt Text

  8. Now run the app again by hitting the play button. We can see our label on the Simulator. We're now mid-level iOS Developers!! ⭐

    alt text

2. Customizing an app

  1. Next we're going to add some dynamic data to our app. This is typically done by connecting to an API so we can get real time data from the Internet. We'll come back to this network code in a later workshop, but for now_....here's one we prepared earlier!_ Download this file:

  2. Drag the downloaded file NewsFetching.swift into the Project Navigator section of your app

    Alt Text

  3. This file contains 2 objects:

    1. NewsFetcher: A class for fetching news articles from newsapi.org
    2. NewsItem: A struct for holding the fetched news article data
  4. In order to update our label, we have to add it to our ViewController.swift:

        class ViewController: UIViewController {
    
          @IBOutlet var content: UILabel!
    
          ...
    
  5. Next, since we've included NewsFetching.swift in our project, we can now use the NewsFetcher to fetch actual data. Add this code to the viewDidLoad() method of ViewController.swift:

        override func viewDidLoad() {
            super.viewDidLoad()
            // Create a new instance of NewsFetcher to do our fetching
            let fetcher = NewsFetcher()
            // Ask fetcher to get latest articles
            // This is an asynchronous call
            // Code between { ... } will be executed when the data has been fetched
            // Note: Result is a Swift type that captures either success or failure in a single enum
            fetcher.getLatestArticles { [weak self] (result: Result<[NewsItem], NewsFetcherError>) in
                switch result {
                case .success(let articles):
                    // If fetching was successful, update content to show first title
                    self?.content.text = articles.first?.title
                case .failure(let error):
                    // If fetching failed, update content to show the error
                    self?.content.text = "\(error)"
                }
            }
        }
  6. Now run the app again by hitting the play button. We will need to wait while data is fetched from the server, but then we should see our label updated to show current content. Did it work??

  7. Whoops - we forget to connect our label between our source file (ViewController.swift) and our storyboard (Main.storyboard). Carefully follow the steps here to open the assistant editor and connect the label from the storyboard to the label in code.

    Alt Text

  8. Run the app again by hitting the play button. We will need to wait while data is fetched, but then we should see content label being updated to show a real title. Oops, the text is getting cropped!

    alt text
  9. We need to add some constraints to make the label size larger.

    Alt Text

  10. Run the app again by hitting the play button. We will need to wait while data is fetched, but then we should see content label being updated to show a real title. Woohoo!! We're now senior iOS Developers!! 🏆

    alt text

3. Showing different data

  1. Showing a single title is a bit dull. Let's make this app truly great and show a whole scrolling table of titles!! To do this we need a UITableView rather than a UILabel. A UITableView is what we see a lot in iOS apps. It's a scrolling list of repetitive information. In our case, we will show a scrolling list of NewsItems.

  2. Open Main.storyboard and delete the content label you created earlier. Now drag in a UITableView.

    Alt Text

  3. Now we need to change the label declaration to aUITableView declaration:

    class ViewController: UIViewController {
        @IBOutlet var tableView: UITableView!
        ...
    
  4. Don't forget to connect the outlet on the UITableView in the Storyboard.

    Alt Text

  5. A UITableView needs a UITableViewDataSource to tell it what information to show. At minimum, a UITableViewDataSource provides this information:

    1. numberOfSections: How many sections the table contains (a section is a group of items)
    2. numberOfRowsInSection: How many rows the table contains (a row for each NewsItem)
    3. cellForRow: A visual representation of the NewsItems
  6. Update ViewController so it is able to act as a UITableViewDataSource in ViewController.swift:

    class ViewController: UIViewController {
        @IBOutlet var tableView: UITableView!
        
        var articles = [NewsItem]()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // Configure the TableView to reuse cells based on an identifier
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: "ArticleCell")
            
            // Configure the TableView to use our class as the Data Source
            tableView.dataSource = self
            
            // Create a new instance of NewsFetcher to do our fetching
            let fetcher = NewsFetcher()
            // Ask fetcher to get latest articles
            // This is an asynchronous call
            // Code between { ... } will be executed when the data has been fetched
            // Note: Result is a Swift type that captures either success or failure in a single enum
            fetcher.getLatestArticles { [weak self] (result: Result<[NewsItem], NewsFetcherError>) in
                switch result {
                case .success(let newArticles):
                    // If fetching was successful, set the articles variable from ViewController with new articles
                    self?.articles = newArticles
                    
                    // The tell the tableView it should reload its data
                    self?.tableView.reloadData()
                case .failure(let error):
                    // If fetching failed, print the error
                    print(error.localizedDescription)
                }
            }
        }
    }
    
    extension ViewController: UITableViewDataSource {
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return articles.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            //// Complete me with cells that show the data from articles
            return UITableViewCell()
        }
    }
  7. Run the app by hitting the play button. We will need to wait while data is fetched, then we should see a scrollable table of items. The table is beautiful....but the rows are empty.

    alt text
  8. We need to use the data from articles to populate each row. This is done by configuring our UITableViewCells in the cellForRow: method:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: "ArticleCell", for: indexPath)
      cell.textLabel?.text = articles[indexPath.row].title
      return cell
    }
  9. Now one more time, hit that play button and run the app. After the data is fetched, we should see a scrollable table of NewsItems. 🎉

    alt text
  10. The last step is to form a startup and become app billionaires!! 🤑 🤑 🤑