Students will work with table views, learn about protocols, and implement the UITableViewDataSource and UITableViewDelegate protocols to build a Solar System directory.
Students who complete this project independently can:
- instantiate and place a UITableView on the screen
- work with UITableViewControllers
- implement a master-detail interface
- apply the UITableViewDataSource protocol
- use the UITableViewDelegate protocol methods to respond to user interaction
- instantiate and place UIImages on the screen
- use a Model Object Controller to access model objects
When you create your project, select the single view application, make sure that you choose the user Interface Storyboard and not SwiftUI. If you create your project after selecting SwiftUI, you will need to delete your project and try again.
Create your Planet Model class that will hold the Name, ImageName, Diameter, Day-length, and MaxMillionKMsFromSun.
- Add a new
Planet.swift
file and define a newPlanet
class. - Add your properties, and be careful to choose the appropriate data types. The values of Day length and maxMillionKMsFromSun will have a decimal point, while Diameter will not.
- Create your
memberwise
Initializer that takes the parameters for each property.
Create your PlanetController class that will hold your planets array, which will receive its value from a computed property.
- Add a new
PlanetController.swift
file. - Create a new computed property called
planets
and set it to be of-type an array ofPlanet
objects. - Create your
Planet
objects. Here are the details for each planet:
- let mercury = Planet(planetName: “Mercury”, planetImageName: “mercury”, planetDiameter: 4880, planetDayLength: 87.969, maxMillionKMsFromSun: 43.0)
- let venus = Planet(planetName: “Venus”, planetImageName: “venus”, planetDiameter: 12104, planetDayLength: 2802, maxMillionKMsFromSun: 108.2)
- let earth = Planet(planetName: “Earth”, planetImageName: “earth”, planetDiameter: 12756, planetDayLength: 24, maxMillionKMsFromSun: 149.6)
- let mars = Planet(planetName: “Mars”, planetImageName: “mars”, planetDiameter: 6792, planetDayLength: 24.7, maxMillionKMsFromSun: 227.9)
- let jupiter = Planet(planetName: “Jupiter”, planetImageName: “jupiter”, planetDiameter: 142984, planetDayLength: 9.9, maxMillionKMsFromSun: 778.6)
- let saturn = Planet(planetName: “Saturn”, planetImageName: “saturn”, planetDiameter: 120536, planetDayLength: 10.7, maxMillionKMsFromSun: 1433.5)
- let uranus = Planet(planetName: “Uranus”, planetImageName: “uranus”, planetDiameter: 51118, planetDayLength: 17.2, maxMillionKMsFromSun: 2872.5)
- let neptune = Planet(planetName: “Neptune”, planetImageName: “neptune”, planetDiameter: 49528, planetDayLength: 16.1, maxMillionKMsFromSun: 4495.1)
- let pluto = Planet(planetName: “Pluto”, planetImageName: “pluto”, planetDiameter: 2370, planetDayLength: 153.3, maxMillionKMsFromSun: 5906.4)
- Return an array of the planet objects you just created
- Set your
planets
to be static so we can access them with an instance of ourPlanetController
Build a view that lists the planets using a UITableViewController
scene. Implement the UITableViewDataSource
protocol methods (refer to the documentation for a refresher if needed). Note that one could use a UIViewControllerwith
a UITableView
placed on it, but UITableViewController
implements a full-screen UITableView by default.
Step by step process
- Delete the initial view controller that was autogenerated in the
Main.storyboard
file. - Add a UITableViewController as your root ViewController in the
Main.storyboard
file. Embed in a UINavigationController - Implement the UITableViewDataSource methods using the
PlanetController.planets
array. - Don’t forget to manage your
reuseIdentifer
- Set up your cells to display the name, image, and index of the planet. Note: Basic
UITableView Cells
have aUIImage
by default.
Feel free to experiment with the content modes on the cell’s UIImageView to display the image in different ways.
Readability: The UITableViewController subclass template comes with a lot of boilerplate and commented code. For readability, please remove all unused boilerplate from your code.
Build a UIViewController scene in the storyboard with UI elements to display an image of the planet and the details of a planet, such as distance from the sun, day length, and Diameter. Make a planet variable for the tableViewController’s prepare(for segue: …)
function to pass the planet that is tapped on. Create and call a function that updates the UI elements to display the information from the planet
variable.
Step by step process:
- Add a new UIViewController scene to Main.storyboard
- Create a PlanetDetailViewController file as a subclass of UIViewController and set the class of your detail view scene Hint: In the Main.storyboard, click the yellow circle above the new UIViewController scene, then select the Identity Inspector (the third icon from the right) on the top right of the window. In the text field that says “Class:”, type the name of the new
UIViewController
subclass you just made in the previous step (PlanetDetailViewController
) - Add a UIImageView and UILabels to display the data note: Experiment with Autolayout automatic constraints or UIStackViews to create an appealing detail view
- Create outlets from the UIImageView and UILabels to your PlanetDetailViewController class. If Xcode doesn’t let you create the outlets, make sure that you’ve correctly set the class of the detail view scene from the last step.
- Add an optional planet property (of type Planet); this property will be set by the Master List View when performing the segue
- Add a new function called updateViews. The function ensures that the PlanetDetailViewController’s planet property, created in step 5, has a planet passed to it. It does this by unwrapping it, then updating the view controller’s title, UIImageView, and UILabels with the planet’s data. Please note that this is a widespread design pattern, so be sure to commit it to memory. If you have a detail view or table view cell template that displays data, using the ‘updateViews’ method will take the model data passed from the previous view controller’s prepareForSegue function and update the view’s subviews with it.
- Update the viewDidLoad() function to call the updateViews function. You can test your view and the update function by setting the detail view as the initial view controller. In the viewDidLoad, assign self.planet to PlanetController.planets[0], before calling updateViews. Be sure to reverse those changes when done checking that the view works, or you may have undesired behavior as you create your segue, also make sure to leave the updateViews function in the viewDidLoad.
Create a segue between your List View and Detail View that will pass the selected planet to the detail view for display.
Step by step process:
- Option-drag from your prototype cell in the List View to the Detail View to create a “show” segue.
- Select the segue and give it an identifier note: For best practice, the identifier should describe what the segue does, such as
toPlanetDetail
- Add the prepareForSegue function to your PlanetListViewController class note: Remember that prepareForSegue will get called on all segues triggered from the current scene and accompanying view controller class
- Implement the
prepareForSegue method
by checking for the correct segue identifier, capturing an instance of the selected planet, capturing an instance of the PlanetDetailViewController, and setting the planet property of the PlanetDetailViewController Hint: Remember, thePlanetDetailViewController
will use theplanet
property to update itself when it loads to display to the user
Hint:
// Identifier: What segue was triggerd
if segue.identifier ... {
// Index: What cell was tapped
if let index = ... {
// Destination: Where am I going /
guard let destintionVC ... { return }
// Object to send: What Object/Data am I passing?
let objectToSend = ...
// Reciever Object: What object will catch this data
destintionVC.reciever = ...
}
}
Add additional model data to the Planet class, update the PlanetController to include it, and update the PlanetDetailViewController to display it.
- Add an image of the entire Solar System as a header view to the list UITableView
- Create a Unit or UITest that verifies the number of cells in the PlanetListViewController
- Create a Unit or UITest that checks the values of PlanetController.planets
Please refer to CONTRIBUTING.md.
© DevMountain LLC, 2018. Unauthorized use and/or duplication of this material without express and written permission from DevMountain, LLC is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to DevMountain with appropriate and specific direction to the original content.